[hornetq-commits] JBoss hornetq SVN: r9891 - in branches/Branch_New_Paging_preMerge: src/main/org/hornetq/core/client/impl and 27 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Mon Nov 15 16:09:24 EST 2010


Author: clebert.suconic at jboss.com
Date: 2010-11-15 16:09:22 -0500 (Mon, 15 Nov 2010)
New Revision: 9891

Added:
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/LivePageCache.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PageCache.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PageCursorProvider.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PagePosition.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PageSubscription.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PagedReference.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PagedReferenceImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/LivePageCacheImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PageCacheImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PageCursorProviderImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PagePositionImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PageSubscriptionImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/RouteContextList.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/transaction/TransactionOperationAbstract.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/utils/SoftValueHashMap.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/paging/PageCursorTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/paging/PagePositionTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PagePositionTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/util/SoftValueMapTest.java
Modified:
   branches/Branch_New_Paging_preMerge/hornetq.ipr
   branches/Branch_New_Paging_preMerge/hornetq.iws
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/client/impl/ClientConsumerImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/Page.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PageTransactionInfo.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagedMessage.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagingManager.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagingStore.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagingStoreFactory.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PageImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PageTransactionInfoImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagedMessageImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagingManagerImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagingStoreFactoryNIO.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/TestSupportPageStore.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/StorageManager.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/impl/journal/JournalStorageManager.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/impl/journal/OperationContextImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/impl/nullpm/NullStorageManager.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/AddressManager.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/Bindings.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/BindingsFactory.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/PostOffice.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/BindingsImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/PostOfficeImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/SimpleAddressManager.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/WildcardAddressManager.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/replication/impl/ReplicationEndpointImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/MessageReference.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/Queue.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/QueueFactory.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/RoutingContext.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/ServerMessage.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/ServerSession.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/cluster/impl/RemoteQueueBindingImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/HornetQServerImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/LastValueQueue.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/MessageReferenceImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/QueueFactoryImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/QueueImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/RoutingContextImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/ServerConsumerImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/ServerMessageImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/ServerSessionImpl.java
   branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/transaction/TransactionPropertyIndexes.java
   branches/Branch_New_Paging_preMerge/tests/jms-tests/src/org/hornetq/jms/tests/BrowserTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/concurrent/server/impl/QueueTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/client/PagingTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/paging/PageCrashTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/persistence/DeleteMessagesOnStartupTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/persistence/RestartSMTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/persistence/StorageManagerTestBase.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/replication/ReplicationTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/timing/core/server/impl/QueueImplTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PageImplTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingManagerImplTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingStoreImplTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/postoffice/impl/BindingsImplTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/postoffice/impl/DuplicateDetectionUnitTest.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/postoffice/impl/FakeQueue.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/server/impl/fakes/FakeQueueFactory.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/util/RandomUtil.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/util/ServiceTestBase.java
   branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/util/UnitTestCase.java
Log:
Update branch on paging

Modified: branches/Branch_New_Paging_preMerge/hornetq.ipr
===================================================================
--- branches/Branch_New_Paging_preMerge/hornetq.ipr	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/hornetq.ipr	2010-11-15 21:09:22 UTC (rev 9891)
@@ -631,7 +631,7 @@
       <module fileurl="file://$PROJECT_DIR$/tests/hornetq-tests.iml" filepath="$PROJECT_DIR$/tests/hornetq-tests.iml" />
     </modules>
   </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/classes" />
   </component>
   <component name="ResourceManagerContainer">

Modified: branches/Branch_New_Paging_preMerge/hornetq.iws
===================================================================
--- branches/Branch_New_Paging_preMerge/hornetq.iws	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/hornetq.iws	2010-11-15 21:09:22 UTC (rev 9891)
@@ -2,48 +2,14 @@
 <project version="4">
   <component name="ChangeListManager">
     <list default="true" readonly="true" id="a2aae645-dbcd-4d6e-9c99-efa05d93589a" name="Default" comment="">
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/server/ra.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/src/org/hornetq/javaee/example/server" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/server0/hornetq-configuration.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/readme.html" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/src/org/hornetq/javaee/example/server/MDBQueue.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/server0/hornetq-jms.xml" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs/user-manual/en/appserver-integration.xml" afterPath="$PROJECT_DIR$/docs/user-manual/en/appserver-integration.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/config/META-INF/application.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/build.sh" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/src/org/hornetq/javaee/example/MDBRemoteServerClientExample.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/src/org/hornetq/javaee" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/build.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/server" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/src" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/examples/javaee/common/build.xml" afterPath="$PROJECT_DIR$/examples/javaee/common/build.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/config/ant.properties" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/src/org" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/build.bat" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/server0/hornetq-users.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/server/hornetq-configuration.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/server/hornetq-jms.xml" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs/user-manual/en/examples.xml" afterPath="$PROJECT_DIR$/docs/user-manual/en/examples.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/server/jms-ds.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/config/META-INF" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/server0/client-jndi.properties" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/src/org/hornetq/javaee/example" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/src/org/hornetq" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/server0" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/server0/hornetq-beans.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/config/client.jndi.properties" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/examples/javaee/jca-remote/config" />
-    </list>
-    <list id="5341122e-b51c-4e90-b798-7086790ef7e8" name="intellij" comment="">
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/hornetq.iml" afterPath="$PROJECT_DIR$/hornetq.iml" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/examples/javaee/hornetq-javaee-examples.iml" afterPath="$PROJECT_DIR$/examples/javaee/hornetq-javaee-examples.iml" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/hornetq.iws" afterPath="$PROJECT_DIR$/hornetq.iws" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/examples/jms/hornetq-jms-examples.iml" afterPath="$PROJECT_DIR$/examples/jms/hornetq-jms-examples.iml" />
       <change type="MODIFICATION" beforePath="$PROJECT_DIR$/hornetq.ipr" afterPath="$PROJECT_DIR$/hornetq.ipr" />
+      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/hornetq.iws" afterPath="$PROJECT_DIR$/hornetq.iws" />
     </list>
-    <ignored path=".idea/workspace.xml" />
+    <list id="5341122e-b51c-4e90-b798-7086790ef7e8" name="intellij" comment="" />
+    <ignored path="$USER_HOME_GRAILS$/" />
     <ignored path="messaging.iws" />
+    <ignored path=".idea/workspace.xml" />
+    <ignored path="$USER_HOME_GRIFFON$/" />
     <option name="TRACKING_ENABLED" value="true" />
     <option name="SHOW_DIALOG" value="false" />
     <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -138,7 +104,7 @@
         <option name="CONDITION" value="" />
         <option name="LOG_MESSAGE" value="" />
       </breakpoint>
-      <breakpoint url="file://$PROJECT_DIR$/src/main/org/hornetq/integration/jboss/security/JBossASSecurityManager.java" line="145" class="org.hornetq.integration.jboss.security.JBossASSecurityManager" package="org.hornetq.integration.jboss.security">
+      <breakpoint url="file://$PROJECT_DIR$/src/main/org/hornetq/integration/jboss/security/JBossASSecurityManager.java" line="145" class="org.hornetq.integration.jboss.security.JBossASSecurityManager$1" package="org.hornetq.integration.jboss.security">
         <option name="ENABLED" value="true" />
         <option name="LOG_ENABLED" value="false" />
         <option name="LOG_EXPRESSION_ENABLED" value="false" />
@@ -242,7 +208,7 @@
         <option name="CONDITION" value="" />
         <option name="LOG_MESSAGE" value="" />
       </breakpoint>
-      <breakpoint url="file://$PROJECT_DIR$/tests/src/org/hornetq/tests/integration/ra/HornetQMessageHandlerTest.java" line="234" class="org.hornetq.tests.integration.ra.HornetQMessageHandlerTest.DummyMessageEndpoint" package="org.hornetq.tests.integration.ra">
+      <breakpoint url="file://$PROJECT_DIR$/tests/src/org/hornetq/tests/integration/ra/HornetQMessageHandlerTest.java" line="234" class="org.hornetq.tests.integration.ra.HornetQMessageHandlerTest" package="org.hornetq.tests.integration.ra">
         <option name="ENABLED" value="true" />
         <option name="LOG_ENABLED" value="false" />
         <option name="LOG_EXPRESSION_ENABLED" value="false" />
@@ -323,100 +289,24 @@
   <component name="FileColors" enabled="true" enabledForTabs="true" />
   <component name="FileEditorManager">
     <leaf>
-      <file leaf-file-name="MDBRemoteServerClientExample.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/src/org/hornetq/javaee/example/MDBRemoteServerClientExample.java">
+      <file leaf-file-name="PageCursorTest.java" pinned="false" current="true" current-in-tab="true">
+        <entry file="file://$PROJECT_DIR$/tests/src/org/hornetq/tests/integration/paging/PageCursorTest.java">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="95" column="17" selection-start="3054" selection-end="3226" vertical-scroll-proportion="0.0">
-              <folding>
-                <element signature="imports" expanded="true" />
-              </folding>
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="readme.html" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/readme.html">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="46" column="44" selection-start="2573" selection-end="3415" vertical-scroll-proportion="-16.304348">
+            <state line="459" column="11" selection-start="14538" selection-end="14538" vertical-scroll-proportion="0.80944353">
               <folding />
             </state>
           </provider>
         </entry>
       </file>
-      <file leaf-file-name="appserver-integration.xml" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/docs/user-manual/en/appserver-integration.xml">
+      <file leaf-file-name="SpringBindingRegistry.java" pinned="false" current="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/src/main/org/hornetq/integration/spring/SpringBindingRegistry.java">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="836" column="101" selection-start="48141" selection-end="48141" vertical-scroll-proportion="-15.04">
+            <state line="3" column="47" selection-start="140" selection-end="140" vertical-scroll-proportion="0.0">
               <folding />
             </state>
           </provider>
         </entry>
       </file>
-      <file leaf-file-name="examples.xml" pinned="false" current="true" current-in-tab="true">
-        <entry file="file://$PROJECT_DIR$/docs/user-manual/en/examples.xml">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="534" column="124" selection-start="33920" selection-end="33920" vertical-scroll-proportion="0.4304762">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="ra.xml" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/server/ra.xml">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="61" column="27" selection-start="2184" selection-end="3025" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="hornetq-configuration.xml" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/server0/hornetq-configuration.xml">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="46" column="49" selection-start="1976" selection-end="1976" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="MDBQueue.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/src/org/hornetq/javaee/example/server/MDBQueue.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="46" column="25" selection-start="1849" selection-end="1865" vertical-scroll-proportion="0.0">
-              <folding>
-                <element signature="imports" expanded="true" />
-              </folding>
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="StatelessSenderService.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/examples/javaee/jca-config/src/org/hornetq/javaee/example/server2/StatelessSenderService.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="23" column="17" selection-start="806" selection-end="806" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="StatelessSender.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/examples/javaee/jca-config/src/org/hornetq/javaee/example/server2/StatelessSender.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="50" column="59" selection-start="1556" selection-end="1609" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="MDB_BMTClientExample.java" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/examples/javaee/mdb-bmt/src/org/hornetq/javaee/example/MDB_BMTClientExample.java">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="71" column="32" selection-start="2239" selection-end="2468" vertical-scroll-proportion="0.0">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
     </leaf>
   </component>
   <component name="FindManager">
@@ -424,10 +314,13 @@
       <setting name="OPEN_NEW_TAB" value="true" />
     </FindUsagesManager>
   </component>
+  <component name="Git.Settings">
+    <option name="GIT_EXECUTABLE" value="git" />
+    <option name="CHECKOUT_INCLUDE_TAGS" value="false" />
+  </component>
   <component name="IdeDocumentHistory">
     <option name="changedFiles">
       <list>
-        <option value="$PROJECT_DIR$/examples/javaee/jca-config/build.xml" />
         <option value="$PROJECT_DIR$/examples/javaee/jca-remote/config/jndi.properties" />
         <option value="$PROJECT_DIR$/examples/javaee/jca-remote/server0/hornetq-beans.xml" />
         <option value="$PROJECT_DIR$/examples/javaee/jca-remote/server/hornetq-configuration.xml" />
@@ -443,6 +336,7 @@
         <option value="$PROJECT_DIR$/examples/javaee/jca-remote/readme.html" />
         <option value="$PROJECT_DIR$/docs/user-manual/en/appserver-integration.xml" />
         <option value="$PROJECT_DIR$/docs/user-manual/en/examples.xml" />
+        <option value="$PROJECT_DIR$/tests/src/org/hornetq/tests/integration/paging/PageCursorTest.java" />
       </list>
     </option>
   </component>
@@ -1355,7 +1249,7 @@
     <option name="STATE" value="0" />
   </component>
   <component name="ProjectView">
-    <navigator currentView="ProjectPane" proportions="" version="1" splitterProportion="0.5">
+    <navigator currentView="PackagesPane" proportions="" version="1" splitterProportion="0.5">
       <flattenPackages />
       <showMembers />
       <showModules />
@@ -1367,7 +1261,6 @@
       <sortByType />
     </navigator>
     <panes>
-      <pane id="PackagesPane" />
       <pane id="ProjectPane">
         <subPane>
           <PATH>
@@ -1382,7 +1275,7 @@
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="javaee" />
+              <option name="myItemId" value="trunk" />
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
             </PATH_ELEMENT>
           </PATH>
@@ -1392,35 +1285,13 @@
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="javaee" />
+              <option name="myItemId" value="trunk" />
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="mdb-bmt" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="hornetq" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="javaee" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="mdb-bmt" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
               <option name="myItemId" value="src" />
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
             </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="example" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
           </PATH>
           <PATH>
             <PATH_ELEMENT>
@@ -1428,33 +1299,15 @@
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="javaee" />
+              <option name="myItemId" value="trunk" />
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="jca-remote" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="hornetq" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="javaee" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="jca-remote" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
               <option name="myItemId" value="src" />
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="example" />
+              <option name="myItemId" value="main" />
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
             </PATH_ELEMENT>
           </PATH>
@@ -1464,43 +1317,21 @@
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="javaee" />
+              <option name="myItemId" value="trunk" />
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="jca-remote" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
               <option name="myItemId" value="src" />
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="example" />
+              <option name="myItemId" value="main" />
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="server" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
               <option name="myItemId" value="hornetq" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="javaee" />
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
             </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="jca-remote" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="server0" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
           </PATH>
           <PATH>
             <PATH_ELEMENT>
@@ -1508,186 +1339,94 @@
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="javaee" />
+              <option name="myItemId" value="core" />
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
             </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="jca-remote" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="server" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
           </PATH>
+        </subPane>
+      </pane>
+      <pane id="Scope" />
+      <pane id="Favorites" />
+      <pane id="PackagesPane">
+        <subPane>
           <PATH>
             <PATH_ELEMENT>
               <option name="myItemId" value="hornetq" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="javaee" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+              <option name="myItemId" value="hornetq-tests" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode" />
             </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="jca-remote" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="config" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
           </PATH>
           <PATH>
             <PATH_ELEMENT>
               <option name="myItemId" value="hornetq" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="javaee" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+              <option name="myItemId" value="hornetq-tests" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="jca-config" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+              <option name="myItemId" value="org.hornetq.tests" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageElementNode" />
             </PATH_ELEMENT>
           </PATH>
           <PATH>
             <PATH_ELEMENT>
               <option name="myItemId" value="hornetq" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="javaee" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+              <option name="myItemId" value="hornetq-tests" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="common" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+              <option name="myItemId" value="org.hornetq.tests" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageElementNode" />
             </PATH_ELEMENT>
-          </PATH>
-          <PATH>
             <PATH_ELEMENT>
-              <option name="myItemId" value="hornetq" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+              <option name="myItemId" value="integration" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageElementNode" />
             </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="hornetq-jms-examples" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="jms" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
           </PATH>
           <PATH>
             <PATH_ELEMENT>
               <option name="myItemId" value="hornetq" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="hornetq-jms-examples" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
+              <option name="myItemId" value="hornetq-tests" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="jms" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+              <option name="myItemId" value="org.hornetq.tests" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageElementNode" />
             </PATH_ELEMENT>
             <PATH_ELEMENT>
-              <option name="myItemId" value="queue" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+              <option name="myItemId" value="integration" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageElementNode" />
             </PATH_ELEMENT>
-          </PATH>
-          <PATH>
             <PATH_ELEMENT>
-              <option name="myItemId" value="hornetq" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+              <option name="myItemId" value="paging" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageElementNode" />
             </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="hornetq-jms-examples" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="jms" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="queue" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="src" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="example" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
           </PATH>
           <PATH>
             <PATH_ELEMENT>
               <option name="myItemId" value="hornetq" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
             </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="hornetq-jms-examples" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="common" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
           </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="hornetq" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="hornetq-jms-examples" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="common" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="src" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="example" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="hornetq" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="hornetq-jms-examples" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="common" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="config" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
         </subPane>
       </pane>
-      <pane id="Scope" />
-      <pane id="Favorites" />
     </panes>
   </component>
   <component name="PropertiesComponent">
     <property name="FileHistory.org.jetbrains.idea.svn.history.SvnHistoryProvider_flatWidth1" value="287" />
     <property name="FileHistory.org.jetbrains.idea.svn.history.SvnHistoryProvider_flatWidth0" value="225" />
-    <property name="project.structure.last.edited" value="Modules" />
+    <property name="project.structure.last.edited" value="Project" />
     <property name="FileHistory.org.jetbrains.idea.svn.history.SvnHistoryProvider_flatWidth3" value="35" />
     <property name="FileHistory.org.jetbrains.idea.svn.history.SvnHistoryProvider_flatWidth2" value="246" />
     <property name="project.structure.proportion" value="0.15" />
@@ -1741,34 +1480,7 @@
       <recent name="org.hornetq.api.core.client.HornetQClient" />
     </key>
   </component>
-  <component name="RunManager" selected="Remote.server">
-    <configuration default="false" name="DiscoveryTest.testSimpleBroadcastSpecificNIC" type="JUnit" factoryName="JUnit" temporary="true">
-      <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="emma">
-        <pattern>
-          <option name="PATTERN" value="org.hornetq.tests.integration.discovery.*" />
-          <option name="ENABLED" value="true" />
-        </pattern>
-      </extension>
-      <module name="hornetq-tests" />
-      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
-      <option name="ALTERNATIVE_JRE_PATH" value="" />
-      <option name="PACKAGE_NAME" value="org.hornetq.tests.integration.discovery" />
-      <option name="MAIN_CLASS_NAME" value="org.hornetq.tests.integration.discovery.DiscoveryTest" />
-      <option name="METHOD_NAME" value="testSimpleBroadcastSpecificNIC" />
-      <option name="TEST_OBJECT" value="method" />
-      <option name="VM_PARAMETERS" value="-Djava.util.logging.config.file=./src/config/trunk/clustered/logging.properties -Djava.library.path=native/bin" />
-      <option name="PARAMETERS" value="" />
-      <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
-      <option name="ENV_VARIABLES" />
-      <option name="PASS_PARENT_ENVS" value="true" />
-      <option name="TEST_SEARCH_SCOPE">
-        <value defaultName="moduleWithDependencies" />
-      </option>
-      <envs />
-      <RunnerSettings RunnerId="Run" />
-      <ConfigurationWrapper RunnerId="Run" />
-      <method />
-    </configuration>
+  <component name="RunManager" selected="JUnit.PageCursorTest">
     <configuration default="false" name="QueueExample" type="Application" factoryName="Application" temporary="true">
       <extension name="coverage" enabled="false" merge="false" runner="emma">
         <pattern>
@@ -1776,6 +1488,7 @@
           <option name="ENABLED" value="true" />
         </pattern>
       </extension>
+      <extension name="snapshooter" />
       <option name="MAIN_CLASS_NAME" value="org.hornetq.jms.example.QueueExample" />
       <option name="VM_PARAMETERS" />
       <option name="PROGRAM_PARAMETERS" />
@@ -1798,6 +1511,7 @@
           <option name="ENABLED" value="true" />
         </pattern>
       </extension>
+      <extension name="snapshooter" />
       <module name="hornetq-tests" />
       <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
       <option name="ALTERNATIVE_JRE_PATH" value="" />
@@ -1831,6 +1545,7 @@
           <option name="ENABLED" value="true" />
         </pattern>
       </extension>
+      <extension name="snapshooter" />
       <module name="hornetq-tests" />
       <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
       <option name="ALTERNATIVE_JRE_PATH" value="" />
@@ -1858,6 +1573,7 @@
           <option name="ENABLED" value="true" />
         </pattern>
       </extension>
+      <extension name="snapshooter" />
       <module name="hornetq-tests" />
       <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
       <option name="ALTERNATIVE_JRE_PATH" value="" />
@@ -1878,11 +1594,40 @@
       <ConfigurationWrapper RunnerId="Run" />
       <method />
     </configuration>
+    <configuration default="false" name="PageCursorTest" type="JUnit" factoryName="JUnit" temporary="true">
+      <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="emma">
+        <pattern>
+          <option name="PATTERN" value="org.hornetq.tests.integration.paging.*" />
+          <option name="ENABLED" value="true" />
+        </pattern>
+      </extension>
+      <extension name="snapshooter" />
+      <module name="hornetq-tests" />
+      <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+      <option name="ALTERNATIVE_JRE_PATH" value="" />
+      <option name="PACKAGE_NAME" value="org.hornetq.tests.integration.paging" />
+      <option name="MAIN_CLASS_NAME" value="org.hornetq.tests.integration.paging.PageCursorTest" />
+      <option name="METHOD_NAME" value="" />
+      <option name="TEST_OBJECT" value="class" />
+      <option name="VM_PARAMETERS" value="-Djava.util.logging.config.file=./src/config/trunk/clustered/logging.properties -Djava.library.path=native/bin" />
+      <option name="PARAMETERS" value="" />
+      <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+      <option name="ENV_VARIABLES" />
+      <option name="PASS_PARENT_ENVS" value="true" />
+      <option name="TEST_SEARCH_SCOPE">
+        <value defaultName="moduleWithDependencies" />
+      </option>
+      <envs />
+      <RunnerSettings RunnerId="Run" />
+      <ConfigurationWrapper RunnerId="Run" />
+      <method />
+    </configuration>
     <configuration default="true" type="PHPUnitRunConfigurationType" factoryName="PHPUnit">
       <method>
         <option name="AntTarget" enabled="false" />
         <option name="BuildArtifacts" enabled="false" />
         <option name="Maven.BeforeRunTask" enabled="false" />
+        <option name="ValidateXdebugSetup" enabled="true" />
       </method>
     </configuration>
     <configuration default="true" type="Remote" factoryName="Remote">
@@ -1917,6 +1662,7 @@
     </configuration>
     <configuration default="true" type="Application" factoryName="Application">
       <extension name="coverage" enabled="false" merge="false" runner="emma" />
+      <extension name="snapshooter" />
       <option name="MAIN_CLASS_NAME" />
       <option name="VM_PARAMETERS" />
       <option name="PROGRAM_PARAMETERS" />
@@ -1937,6 +1683,7 @@
     </configuration>
     <configuration default="true" type="JUnit" factoryName="JUnit">
       <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="emma" />
+      <extension name="snapshooter" />
       <module name="" />
       <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
       <option name="ALTERNATIVE_JRE_PATH" value="" />
@@ -1967,6 +1714,7 @@
           <option name="ENABLED" value="true" />
         </pattern>
       </extension>
+      <extension name="snapshooter" />
       <module name="hornetq-tests" />
       <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
       <option name="ALTERNATIVE_JRE_PATH" />
@@ -2000,6 +1748,7 @@
           <option name="ENABLED" value="true" />
         </pattern>
       </extension>
+      <extension name="snapshooter" />
       <module name="hornetq-tests" />
       <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
       <option name="ALTERNATIVE_JRE_PATH" value="" />
@@ -2027,6 +1776,7 @@
           <option name="ENABLED" value="true" />
         </pattern>
       </extension>
+      <extension name="snapshooter" />
       <module name="hornetq-tests" />
       <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
       <option name="ALTERNATIVE_JRE_PATH" value="" />
@@ -2064,13 +1814,7 @@
         <option name="TRANSPORT" value="0" />
         <option name="LOCAL" value="false" />
       </RunnerSettings>
-      <RunnerSettings RunnerId="Debug">
-        <option name="DEBUG_PORT" value="5005" />
-        <option name="TRANSPORT" value="0" />
-        <option name="LOCAL" value="false" />
-      </RunnerSettings>
       <ConfigurationWrapper RunnerId="Debug" />
-      <ConfigurationWrapper RunnerId="Debug" />
       <method />
     </configuration>
     <configuration default="false" name="EnqueueDurable" type="Application" factoryName="Application">
@@ -2080,6 +1824,7 @@
           <option name="ENABLED" value="true" />
         </pattern>
       </extension>
+      <extension name="snapshooter" />
       <option name="MAIN_CLASS_NAME" value="org.hornetq.test.EnqueueDurable" />
       <option name="VM_PARAMETERS" value="" />
       <option name="PROGRAM_PARAMETERS" value="127.0.0.1" />
@@ -2096,11 +1841,11 @@
       <method />
     </configuration>
     <list size="10">
-      <item index="0" class="java.lang.String" itemvalue="JUnit.DiscoveryTest.testSimpleBroadcastSpecificNIC" />
-      <item index="1" class="java.lang.String" itemvalue="Application.QueueExample" />
-      <item index="2" class="java.lang.String" itemvalue="JUnit.HornetQMessageHandlerTest.testSelectorNotChanged" />
-      <item index="3" class="java.lang.String" itemvalue="JUnit.HornetQMessageHandlerTest.testSelectorChanged" />
-      <item index="4" class="java.lang.String" itemvalue="JUnit.HornetQMessageHandlerTest" />
+      <item index="0" class="java.lang.String" itemvalue="Application.QueueExample" />
+      <item index="1" class="java.lang.String" itemvalue="JUnit.HornetQMessageHandlerTest.testSelectorNotChanged" />
+      <item index="2" class="java.lang.String" itemvalue="JUnit.HornetQMessageHandlerTest.testSelectorChanged" />
+      <item index="3" class="java.lang.String" itemvalue="JUnit.HornetQMessageHandlerTest" />
+      <item index="4" class="java.lang.String" itemvalue="JUnit.PageCursorTest" />
       <item index="5" class="java.lang.String" itemvalue="JUnit.LargeMessageTest" />
       <item index="6" class="java.lang.String" itemvalue="JUnit.NettyFailoverTest.test" />
       <item index="7" class="java.lang.String" itemvalue="JUnit.GroupingFailoverReplicationTest.test" />
@@ -2123,6 +1868,7 @@
     <option name="UPDATE_LOCK_ON_DEMAND" value="false" />
     <option name="IGNORE_SPACES_IN_MERGE" value="false" />
     <option name="DETECT_NESTED_COPIES" value="false" />
+    <option name="CHECK_NESTED_FOR_QUICK_MERGE" value="false" />
     <option name="IGNORE_SPACES_IN_ANNOTATE" value="true" />
     <option name="SHOW_MERGE_SOURCES_IN_ANNOTATE" value="true" />
     <configuration useDefault="false">$PROJECT_DIR$/../../.subversion</configuration>
@@ -2183,26 +1929,28 @@
     </todo-panel>
   </component>
   <component name="ToolWindowManager">
-    <frame x="-3" y="25" width="1926" height="1033" extended-state="6" />
+    <frame x="0" y="22" width="1440" height="742" extended-state="0" />
     <editor active="false" />
     <layout>
-      <window_info id="Changes" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.34723788" sideWeight="0.0" order="7" side_tool="false" content_ui="tabs" />
+      <window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.34615386" sideWeight="0.0" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
       <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
-      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.48703495" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
       <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.17925592" sideWeight="0.0" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="IDEtalk Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
+      <window_info id="IDEtalk" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
       <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.17587373" sideWeight="0.0" order="7" side_tool="false" content_ui="tabs" />
-      <window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.16344294" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
-      <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.24959914" sideWeight="0.7006937" order="1" side_tool="false" content_ui="tabs" />
+      <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.24946082" sideWeight="0.64456236" order="1" side_tool="false" content_ui="tabs" />
       <window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
-      <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.17263496" sideWeight="0.64487034" order="0" side_tool="false" content_ui="tabs" />
+      <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
+      <window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.22142343" sideWeight="0.82758623" order="0" side_tool="false" content_ui="tabs" />
       <window_info id="Dependency Viewer" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.20599613" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
       <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
       <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
+      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.48703495" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
       <window_info id="Dataflow to this" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
-      <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
+      <window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.16312997" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
       <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
     </layout>
@@ -2860,118 +2608,84 @@
     </buildFile>
   </component>
   <component name="editorHistoryManager">
-    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/server0/client-jndi.properties">
+    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-config/src/org/hornetq/javaee/example/server2/MDBQueueB.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="14" column="43" selection-start="722" selection-end="722" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
+        <state line="36" column="13" selection-start="1596" selection-end="1596" vertical-scroll-proportion="0.0" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/server0/hornetq-jms.xml">
+    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-config/src/org/hornetq/javaee/example/server/MDBQueueA.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="17" column="29" selection-start="891" selection-end="908" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
+        <state line="36" column="13" selection-start="1593" selection-end="1593" vertical-scroll-proportion="0.0" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-config/src/org/hornetq/javaee/example/server2/MDBQueueB.java">
+    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-config/readme.html">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="36" column="13" selection-start="1596" selection-end="1596" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
+        <state line="149" column="19" selection-start="9467" selection-end="9815" vertical-scroll-proportion="-16.956522" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-config/src/org/hornetq/javaee/example/server/MDBQueueA.java">
+    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/server/jms-ds.xml">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="36" column="13" selection-start="1593" selection-end="1593" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
+        <state line="34" column="31" selection-start="960" selection-end="1628" vertical-scroll-proportion="0.0" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-config/readme.html">
+    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/src/org/hornetq/javaee/example/MDBRemoteServerClientExample.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="149" column="19" selection-start="9467" selection-end="9815" vertical-scroll-proportion="-16.956522">
-          <folding />
-        </state>
+        <state line="95" column="17" selection-start="3054" selection-end="3226" vertical-scroll-proportion="0.0" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/server/jms-ds.xml">
+    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/readme.html">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="34" column="31" selection-start="960" selection-end="1628" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
+        <state line="46" column="44" selection-start="2573" selection-end="3415" vertical-scroll-proportion="0.0" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/server0/hornetq-configuration.xml">
+    <entry file="file://$PROJECT_DIR$/docs/user-manual/en/appserver-integration.xml">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="46" column="49" selection-start="1976" selection-end="1976" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
+        <state line="836" column="101" selection-start="47514" selection-end="47514" vertical-scroll-proportion="0.0" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-config/src/org/hornetq/javaee/example/server2/StatelessSenderService.java">
+    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/server/ra.xml">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="23" column="17" selection-start="806" selection-end="806" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
+        <state line="61" column="27" selection-start="2184" selection-end="3025" vertical-scroll-proportion="0.026258206" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-config/src/org/hornetq/javaee/example/server2/StatelessSender.java">
+    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/server0/hornetq-configuration.xml">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="50" column="59" selection-start="1556" selection-end="1609" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
+        <state line="46" column="49" selection-start="1976" selection-end="1976" vertical-scroll-proportion="0.5536105" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/examples/javaee/mdb-bmt/src/org/hornetq/javaee/example/MDB_BMTClientExample.java">
+    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/src/org/hornetq/javaee/example/server/MDBQueue.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="71" column="32" selection-start="2239" selection-end="2468" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
+        <state line="46" column="25" selection-start="1849" selection-end="1865" vertical-scroll-proportion="0.026258206" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/server/ra.xml">
+    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-config/src/org/hornetq/javaee/example/server2/StatelessSenderService.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="61" column="27" selection-start="2184" selection-end="3025" vertical-scroll-proportion="0.0">
-          <folding />
-        </state>
+        <state line="23" column="17" selection-start="806" selection-end="806" vertical-scroll-proportion="0.60393876" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/src/org/hornetq/javaee/example/MDBRemoteServerClientExample.java">
+    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-config/src/org/hornetq/javaee/example/server2/StatelessSender.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="95" column="17" selection-start="3054" selection-end="3226" vertical-scroll-proportion="0.0">
-          <folding>
-            <element signature="imports" expanded="true" />
-          </folding>
-        </state>
+        <state line="50" column="59" selection-start="1556" selection-end="1609" vertical-scroll-proportion="0.026258206" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/src/org/hornetq/javaee/example/server/MDBQueue.java">
+    <entry file="file://$PROJECT_DIR$/examples/javaee/mdb-bmt/src/org/hornetq/javaee/example/MDB_BMTClientExample.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="46" column="25" selection-start="1849" selection-end="1865" vertical-scroll-proportion="0.0">
-          <folding>
-            <element signature="imports" expanded="true" />
-          </folding>
-        </state>
+        <state line="71" column="32" selection-start="2239" selection-end="2468" vertical-scroll-proportion="0.76367617" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/examples/javaee/jca-remote/readme.html">
+    <entry file="file://$PROJECT_DIR$/docs/user-manual/en/examples.xml">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="46" column="44" selection-start="2573" selection-end="3415" vertical-scroll-proportion="-16.304348">
-          <folding />
-        </state>
+        <state line="534" column="124" selection-start="34000" selection-end="34000" vertical-scroll-proportion="0.51487416" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/docs/user-manual/en/appserver-integration.xml">
+    <entry file="file://$PROJECT_DIR$/src/main/org/hornetq/integration/spring/SpringBindingRegistry.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="836" column="101" selection-start="48141" selection-end="48141" vertical-scroll-proportion="-15.04">
-          <folding />
-        </state>
+        <state line="3" column="47" selection-start="140" selection-end="140" vertical-scroll-proportion="0.0" />
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/docs/user-manual/en/examples.xml">
+    <entry file="file://$PROJECT_DIR$/tests/src/org/hornetq/tests/integration/paging/PageCursorTest.java">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="534" column="124" selection-start="33920" selection-end="33920" vertical-scroll-proportion="0.4304762">
+        <state line="459" column="11" selection-start="14538" selection-end="14538" vertical-scroll-proportion="0.80944353">
           <folding />
         </state>
       </provider>

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/client/impl/ClientConsumerImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/client/impl/ClientConsumerImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/client/impl/ClientConsumerImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -321,7 +321,15 @@
 
    public ClientMessage receive(final long timeout) throws HornetQException
    {
-      return receive(timeout, false);
+      if (isBrowseOnly())
+      {
+         log.warn("receive timeout is not effective on browsing, ignoring timeout");
+         return receive(0, true);
+      }
+      else
+      {
+         return receive(timeout, false);
+      }
    }
 
    public ClientMessage receive() throws HornetQException

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/Page.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/Page.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/Page.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -15,6 +15,8 @@
 
 import java.util.List;
 
+import org.hornetq.core.paging.cursor.LivePageCache;
+
 /**
  * 
  * @see PagingManager
@@ -28,6 +30,8 @@
    void write(PagedMessage message) throws Exception;
 
    List<PagedMessage> read() throws Exception;
+   
+   void setLiveCache(LivePageCache pageCache);
 
    int getSize();
 

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PageTransactionInfo.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PageTransactionInfo.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PageTransactionInfo.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -14,6 +14,8 @@
 package org.hornetq.core.paging;
 
 import org.hornetq.core.journal.EncodingSupport;
+import org.hornetq.core.paging.cursor.PageSubscription;
+import org.hornetq.core.paging.cursor.PagePosition;
 import org.hornetq.core.persistence.StorageManager;
 import org.hornetq.core.transaction.Transaction;
 
@@ -24,8 +26,6 @@
  */
 public interface PageTransactionInfo extends EncodingSupport
 {
-   boolean waitCompletion(int timeoutMilliSeconds) throws Exception;
-
    boolean isCommit();
 
    boolean isRollback();
@@ -42,14 +42,25 @@
    
    void store(StorageManager storageManager, PagingManager pagingManager, Transaction tx) throws Exception;
    
-   void storeUpdate(StorageManager storageManager, PagingManager pagingManager, Transaction tx, int depages) throws Exception;
+   void storeUpdate(StorageManager storageManager, PagingManager pagingManager, Transaction tx) throws Exception;
+   
+   void storeUpdate(StorageManager storageManager, PagingManager pagingManager) throws Exception;
 
    // To be used after the update was stored or reload
-   void update(int update, StorageManager storageManager, PagingManager pagingManager);
+   void onUpdate(int update, StorageManager storageManager, PagingManager pagingManager);
 
    void increment();
+   
+   void increment(int size);
 
    int getNumberOfMessages();
 
-   void markIncomplete();
+   /**
+    * This method will hold the position to be delivered later in case this transaction is pending.
+    * If the tx is not pending, it will return false, so the caller can deliver it right away
+    * @param cursor
+    * @param cursorPos
+    * @return true if the message will be delivered later, false if it should be delivered right away
+    */
+   boolean deliverAfterCommit(PageSubscription cursor, PagePosition cursorPos);
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagedMessage.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagedMessage.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagedMessage.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -28,7 +28,12 @@
  */
 public interface PagedMessage extends EncodingSupport
 {
-   ServerMessage getMessage(StorageManager storageManager);
+   ServerMessage getMessage();
+   
+   /** The queues that were routed during paging */
+   long[] getQueueIDs();
+   
+   void initMessage(StorageManager storageManager);
 
    long getTransactionID();
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagingManager.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagingManager.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagingManager.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -81,4 +81,6 @@
    SimpleString[] getStoreNames();
 
    void deletePageStore(SimpleString storeName) throws Exception;
+   
+   void processReload() throws Exception;
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagingStore.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagingStore.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagingStore.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -13,10 +13,11 @@
 
 package org.hornetq.core.paging;
 
-import java.util.List;
-
 import org.hornetq.api.core.SimpleString;
+import org.hornetq.core.paging.cursor.PageCursorProvider;
 import org.hornetq.core.server.HornetQComponent;
+import org.hornetq.core.server.RouteContextList;
+import org.hornetq.core.server.RoutingContext;
 import org.hornetq.core.server.ServerMessage;
 import org.hornetq.core.settings.impl.AddressFullMessagePolicy;
 
@@ -36,10 +37,17 @@
    SimpleString getAddress();
 
    int getNumberOfPages();
+   
+   // The current page in which the system is writing files
+   int getCurrentWritingPage();
 
    SimpleString getStoreName();
 
    AddressFullMessagePolicy getAddressFullMessagePolicy();
+   
+   long getFirstPage();
+   
+   long getTopPage();
 
    long getPageSizeBytes();
 
@@ -51,19 +59,61 @@
 
    void sync() throws Exception;
 
-   boolean page(List<ServerMessage> messages, long transactionId) throws Exception;
+   boolean page(ServerMessage message, RoutingContext ctx) throws Exception;
 
-   boolean page(ServerMessage message) throws Exception;
+   boolean page(ServerMessage message, RoutingContext ctx, RouteContextList listCtx) throws Exception;
 
    Page createPage(final int page) throws Exception;
+   
+   PagingManager getPagingManager();
+   
+   PageCursorProvider getCursorProvier();
+   
+   void processReload() throws Exception;
+   
+   /** 
+    * Remove the first page from the Writing Queue.
+    * The file will still exist until Page.delete is called, 
+    * So, case the system is reloaded the same Page will be loaded back if delete is not called.
+    *
+    * @throws Exception
+    * 
+    * Note: This should still be part of the interface, even though HornetQ only uses through the 
+    */
+   Page depage() throws Exception;
 
+
+   void forceAnotherPage() throws Exception;
+
+   Page getCurrentPage();
+
+
    /**
     * @return false if a thread was already started, or if not in page mode
     * @throws Exception 
     */
    boolean startDepaging();
+   
+   /** @return true if paging was started, or false if paging was already started before this call */
+   boolean startPaging() throws Exception;
 
+   void stopPaging() throws Exception;
+
    void addSize(int size);
    
    void executeRunnableWhenMemoryAvailable(Runnable runnable);
+   
+   /** This method will hold and producer, but it wait operations to finish before locking (write lock) */
+   void lock();
+   
+   /** 
+    * 
+    * Call this method using the same thread used by the last call of {@link PagingStore#lock()}
+    * 
+    */
+    void unlock();
+
+    /** This is used mostly by tests.
+     *  We will wait any pending runnable to finish its execution */
+    void flushExecutors();
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagingStoreFactory.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagingStoreFactory.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/PagingStoreFactory.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -30,7 +30,7 @@
  */
 public interface PagingStoreFactory
 {
-   PagingStore newStore(SimpleString address, AddressSettings addressSettings) throws Exception;
+   PagingStore newStore(SimpleString address, AddressSettings addressSettings);
 
    void stop() throws InterruptedException;
 

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/LivePageCache.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/LivePageCache.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/LivePageCache.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.paging.cursor;
+
+import org.hornetq.core.paging.PagedMessage;
+
+/**
+ * A LivePageCache
+ *
+ * @author clebertsuconic
+ *
+ *
+ */
+public interface LivePageCache extends PageCache
+{
+   
+   void addLiveMessage(PagedMessage message);
+}

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PageCache.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PageCache.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PageCache.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.paging.cursor;
+
+import org.hornetq.core.paging.Page;
+import org.hornetq.core.paging.PagedMessage;
+
+/**
+ * A PageCache
+ *
+ * @author <a href="mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public interface PageCache
+{
+   Page getPage();
+   
+   long getPageId();
+
+   int getNumberOfMessages();
+   
+   void setMessages(PagedMessage[] messages);
+   
+   /**
+    * If this cache is still being updated
+    * @return
+    */
+   boolean isLive();
+
+   /**
+    * 
+    * @param messageNumber The order of the message on the page
+    * @return
+    */
+   PagedMessage getMessage(int messageNumber);
+
+   /**
+    * When the cache is being created,
+    * We need to first read the files before other threads can get messages from this.
+    */
+   void lock();
+
+   /**
+    * You have to call this method within the same thread you called lock
+    */
+   void unlock();
+   
+   void close();
+
+}

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PageCursorProvider.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PageCursorProvider.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PageCursorProvider.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.paging.cursor;
+
+import org.hornetq.core.filter.Filter;
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.paging.PagingStore;
+
+/**
+ * The provider of Cursor for a given Address
+ *
+ * @author <a href="mailto:clebert.suconic at jboss.com">Clebert Suconic</a>
+ *
+ *
+ */
+public interface PageCursorProvider
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   PageCache getPageCache(PagePosition pos);
+   
+   PagedReference newReference(final PagePosition pos, final PagedMessage msg, PageSubscription sub);
+   
+   void addPageCache(PageCache cache);
+
+   PagingStore getAssociatedStore();
+
+   /**
+    * 
+    * @param queueId The cursorID should be the same as the queueId associated for persistance
+    * @return
+    */
+   PageSubscription getSubscription(long queueId);
+   
+   PageSubscription createSubscription(long queueId, Filter filter, boolean durable);
+   
+   PagedMessage getMessage(PagePosition pos) throws Exception;
+
+   void processReload() throws Exception;
+
+   void stop();
+   
+   void flushExecutors();
+
+   void scheduleCleanup();
+   
+   // Perform the cleanup at the caller's thread (for startup and recovery)
+   void cleanup();
+
+   /**
+    * @param pageCursorImpl
+    */
+   void close(PageSubscription pageCursorImpl);
+   
+   // to be used on tests -------------------------------------------
+   
+   int getCacheSize();
+   
+   void printDebug();
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PagePosition.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PagePosition.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PagePosition.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.paging.cursor;
+
+
+
+/**
+ * A PagePosition
+ *
+ * @author <a href="mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public interface PagePosition extends Comparable<PagePosition>
+{
+
+   // The recordID associated during ack
+   long getRecordID();
+
+   // The recordID associated during ack
+   void setRecordID(long recordID);
+
+   long getPageNr();
+
+   int getMessageNr();
+   
+   void setPageCache(PageCache pageCache);
+   
+   /**
+    * PagePosition will hold the page with a weak reference.
+    * So, this could be eventually null case soft-cache was released
+    * @return
+    */
+   PageCache getPageCache();
+
+   PagePosition nextMessage();
+
+   PagePosition nextPage();
+   
+   /** This will just test if the current position is the immediate next to the parameter position */
+   boolean isRightAfter(PagePosition previous);
+
+}

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PageSubscription.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PageSubscription.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PageSubscription.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.paging.cursor;
+
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.server.Queue;
+import org.hornetq.core.transaction.Transaction;
+import org.hornetq.utils.LinkedListIterator;
+
+/**
+ * A PageCursor
+ *
+ * @author <a href="mailto:clebert.suconic at jboss.com">Clebert Suconic</a>
+ *
+ *
+ */
+public interface PageSubscription
+{
+
+   // Cursor query operations --------------------------------------
+
+   // To be called before the server is down
+   void stop();
+
+   void bookmark(PagePosition position) throws Exception;
+
+   long getId();
+
+   boolean isPersistent();
+   
+   /** Used as a delegate method to pageStore.isPaging() */
+   boolean isPaging();
+
+   public LinkedListIterator<PagedReference> iterator();
+
+   // To be called when the cursor is closed for good. Most likely when the queue is deleted
+   void close() throws Exception;
+
+   void scheduleCleanupCheck();
+
+   void cleanupEntries() throws Exception;
+
+   void disableAutoCleanup();
+
+   void enableAutoCleanup();
+
+   void ack(PagedReference ref) throws Exception;
+
+   // for internal (cursor) classes
+   void ack(PagePosition ref) throws Exception;
+
+   void ackTx(Transaction tx, PagedReference position) throws Exception;
+
+   // for internal (cursor) classes
+   void ackTx(Transaction tx, PagePosition position) throws Exception;
+
+   /**
+    * 
+    * @return the first page in use or MAX_LONG if none is in use
+    */
+   long getFirstPage();
+
+   // Reload operations
+
+   /**
+    * @param position
+    */
+   void reloadACK(PagePosition position);
+
+   /**
+    * To be called when the cursor decided to ignore a position.
+    * @param position
+    */
+   void positionIgnored(PagePosition position);
+
+   /**
+    * To be used to avoid a redelivery of a prepared ACK after load
+    * @param position
+    */
+   void reloadPreparedACK(Transaction tx, PagePosition position);
+
+   void processReload() throws Exception;
+
+   /**      
+    * To be used on redeliveries
+    * @param position
+    */
+   void redeliver(PagePosition position);
+
+   void printDebug();
+
+   /**
+    * @param minPage
+    * @return
+    */
+   boolean isComplete(long page);
+
+   /** wait all the scheduled runnables to finish their current execution */
+   void flushExecutors();
+   
+   void setQueue(Queue queue);
+   
+   Queue getQueue();
+   
+   /**
+    * To be used to requery the reference case the Garbage Collection removed it from the PagedReference as it's using WeakReferences
+    * @param pos
+    * @return
+    */
+   PagedMessage queryMessage(PagePosition pos);
+}

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PagedReference.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PagedReference.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PagedReference.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.paging.cursor;
+
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.server.MessageReference;
+
+/**
+ * A PagedReference
+ *
+ * @author clebert
+ *
+ *
+ */
+public interface PagedReference extends MessageReference
+{
+     PagePosition getPosition();
+     
+     PagedMessage getPagedMessage();
+}

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PagedReferenceImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PagedReferenceImpl.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/PagedReferenceImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.paging.cursor;
+
+import java.lang.ref.WeakReference;
+
+import org.hornetq.api.core.Message;
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.server.MessageReference;
+import org.hornetq.core.server.Queue;
+import org.hornetq.core.server.ServerMessage;
+import org.hornetq.core.transaction.Transaction;
+
+/**
+ * A InternalReference
+ *
+ * @author clebert
+ *
+ *
+ */
+public class PagedReferenceImpl implements PagedReference
+{
+
+   private static final long serialVersionUID = -8640232251318264710L;
+
+   private final PagePosition position;
+
+   private WeakReference<PagedMessage> message;
+   
+   private Long deliveryTime = null;
+   
+   private final PageSubscription subscription;
+
+   public ServerMessage getMessage()
+   {
+      return getPagedMessage().getMessage();
+   }
+
+   public synchronized PagedMessage getPagedMessage()
+   {
+      PagedMessage returnMessage = message.get();
+      
+      // We only keep a few references on the Queue from paging...
+      // Besides those references are SoftReferenced on page cache...
+      // So, this will unlikely be null, 
+      // unless the Queue has stalled for some time after paging
+      if (returnMessage == null)
+      {
+         // reference is gone, we will reconstruct it
+         returnMessage = subscription.queryMessage(position);
+         message = new WeakReference<PagedMessage>(returnMessage);
+      }
+      return returnMessage;
+   }
+
+   public PagePosition getPosition()
+   {
+      return position;
+   }
+
+   public PagedReferenceImpl(final PagePosition position, final PagedMessage message, final PageSubscription subscription)
+   {
+      this.position = position;
+      this.message = new WeakReference<PagedMessage>(message);
+      this.subscription = subscription;
+   }
+
+   public boolean isPaged()
+   {
+      return true;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.MessageReference#copy(org.hornetq.core.server.Queue)
+    */
+   public MessageReference copy(final Queue queue)
+   {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.MessageReference#getScheduledDeliveryTime()
+    */
+   public long getScheduledDeliveryTime()
+   {
+      if (deliveryTime == null)
+      {
+         ServerMessage msg = getMessage();
+         if (msg.containsProperty(Message.HDR_SCHEDULED_DELIVERY_TIME))
+         {
+            deliveryTime = getMessage().getLongProperty(Message.HDR_SCHEDULED_DELIVERY_TIME);
+         }
+         else
+         {
+            deliveryTime = 0l;
+         }
+      }
+      return deliveryTime;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.MessageReference#setScheduledDeliveryTime(long)
+    */
+   public void setScheduledDeliveryTime(final long scheduledDeliveryTime)
+   {
+      deliveryTime = scheduledDeliveryTime;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.MessageReference#getDeliveryCount()
+    */
+   public int getDeliveryCount()
+   {
+      // TODO Auto-generated method stub
+      return 0;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.MessageReference#setDeliveryCount(int)
+    */
+   public void setDeliveryCount(final int deliveryCount)
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.MessageReference#incrementDeliveryCount()
+    */
+   public void incrementDeliveryCount()
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.MessageReference#decrementDeliveryCount()
+    */
+   public void decrementDeliveryCount()
+   {
+      // TODO Auto-generated method stub
+
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.MessageReference#getQueue()
+    */
+   public Queue getQueue()
+   {
+      return subscription.getQueue();
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.MessageReference#handled()
+    */
+   public void handled()
+   {
+      getQueue().referenceHandled();
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.MessageReference#acknowledge()
+    */
+   public void acknowledge() throws Exception
+   {
+      subscription.ack(this);
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.MessageReference#acknowledge(org.hornetq.core.transaction.Transaction)
+    */
+   public void acknowledge(final Transaction tx) throws Exception
+   {
+      subscription.ackTx(tx, this);
+   }
+}

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/LivePageCacheImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/LivePageCacheImpl.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/LivePageCacheImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.paging.cursor.impl;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.hornetq.core.paging.Page;
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.paging.cursor.LivePageCache;
+
+/**
+ * This is the same as PageCache, however this is for the page that's being currently written.
+ *
+ * @author clebertsuconic
+ *
+ *
+ */
+public class LivePageCacheImpl implements LivePageCache
+{
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+   
+   private final List<PagedMessage> messages = new LinkedList<PagedMessage>();
+   
+   private final Page page;
+   
+   private boolean isLive = true;
+   
+   public String toString()
+   {
+      return "LivePacheCacheImpl::page=" + page.getPageId() + " number of messages=" + messages.size() + " isLive = " + isLive;
+   }
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+   
+   public LivePageCacheImpl(final Page page)
+   {
+      this.page = page;
+   }
+
+   // Public --------------------------------------------------------
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCache#getPage()
+    */
+   public Page getPage()
+   {
+      return page;
+   }
+   
+   public long getPageId()
+   {
+      return page.getPageId();
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCache#getNumberOfMessages()
+    */
+   public synchronized int getNumberOfMessages()
+   {
+      return messages.size();
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCache#setMessages(org.hornetq.core.server.ServerMessage[])
+    */
+   public synchronized void setMessages(PagedMessage[] messages)
+   {
+      // This method shouldn't be called on liveCache, but we will provide the implementation for it anyway
+      for (PagedMessage msg : messages)
+      {
+         addLiveMessage(msg);
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCache#getMessage(int)
+    */
+   public synchronized PagedMessage getMessage(int messageNumber)
+   {
+      if (messageNumber < messages.size())
+      {
+         return messages.get(messageNumber);
+      }
+      else
+      {
+         return null;
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCache#lock()
+    */
+   public void lock()
+   {
+      // nothing to be done on live cache
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCache#unlock()
+    */
+   public void unlock()
+   {
+      // nothing to be done on live cache
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCache#isLive()
+    */
+   public synchronized boolean isLive()
+   {
+      return isLive;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.LivePageCache#addLiveMessage(org.hornetq.core.server.ServerMessage)
+    */
+   public synchronized void addLiveMessage(PagedMessage message)
+   {
+      this.messages.add(message);
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.LivePageCache#close()
+    */
+   public synchronized void close()
+   {
+      this.isLive = false;
+   }
+
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PageCacheImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PageCacheImpl.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PageCacheImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.paging.cursor.impl;
+
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.hornetq.core.paging.Page;
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.paging.cursor.PageCache;
+
+/**
+ * The caching associated to a single page.
+ *
+ * @author <a href="mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class PageCacheImpl implements PageCache
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
+   private PagedMessage[] messages;
+
+   private final Page page;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public PageCacheImpl(final Page page)
+   {
+      this.page = page;
+   }
+
+   // Public --------------------------------------------------------
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCache#getPage()
+    */
+   public Page getPage()
+   {
+      return page;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCache#getMessage(int)
+    */
+   public PagedMessage getMessage(final int messageNumber)
+   {
+      lock.readLock().lock();
+      try
+      {
+         if (messageNumber < messages.length)
+         {
+            return messages[messageNumber];
+         }
+         else
+         {
+            return null;
+         }
+      }
+      finally
+      {
+         lock.readLock().unlock();
+      }
+   }
+   
+   public long getPageId()
+   {
+      return page.getPageId();
+   }
+
+   public void lock()
+   {
+      lock.writeLock().lock();
+   }
+
+   public void unlock()
+   {
+      lock.writeLock().unlock();
+   }
+
+   public void setMessages(final PagedMessage[] messages)
+   {
+      this.messages = messages;
+   }
+
+   public int getNumberOfMessages()
+   {
+      lock.readLock().lock();
+      try
+      {
+         return messages.length;
+      }
+      finally
+      {
+         lock.readLock().unlock();
+      }
+   }
+
+   public void close()
+   {
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCache#isLive()
+    */
+   public boolean isLive()
+   {
+      return false;
+   }
+
+   @Override
+   public String toString()
+   {
+      return "PageCacheImpl::page=" + page.getPageId() + " numberOfMessages = " + messages.length;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PageCursorProviderImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PageCursorProviderImpl.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PageCursorProviderImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,464 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.paging.cursor.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Executor;
+
+import org.hornetq.core.filter.Filter;
+import org.hornetq.core.logging.Logger;
+import org.hornetq.core.paging.Page;
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.paging.PagingStore;
+import org.hornetq.core.paging.cursor.PageCache;
+import org.hornetq.core.paging.cursor.PageCursorProvider;
+import org.hornetq.core.paging.cursor.PagePosition;
+import org.hornetq.core.paging.cursor.PageSubscription;
+import org.hornetq.core.paging.cursor.PagedReference;
+import org.hornetq.core.paging.cursor.PagedReferenceImpl;
+import org.hornetq.core.persistence.StorageManager;
+import org.hornetq.utils.ExecutorFactory;
+import org.hornetq.utils.Future;
+import org.hornetq.utils.SoftValueHashMap;
+import org.jboss.netty.util.internal.ConcurrentHashMap;
+
+/**
+ * A PageProviderIMpl
+ * 
+ * TODO: this may be moved entirely into PagingStore as there's an one-to-one relationship here
+ *       However I want to keep this isolated as much as possible during development
+ *
+ * @author <a href="mailto:clebert.suconic at jboss.com">Clebert Suconic</a>
+ *
+ *
+ */
+public class PageCursorProviderImpl implements PageCursorProvider
+{
+   // Constants -----------------------------------------------------
+
+   private static final Logger log = Logger.getLogger(PageCursorProviderImpl.class);
+
+   // Attributes ----------------------------------------------------
+
+   private final PagingStore pagingStore;
+
+   private final StorageManager storageManager;
+
+   private final ExecutorFactory executorFactory;
+
+   private final Executor executor;
+
+   private Map<Long, PageCache> softCache = new SoftValueHashMap<Long, PageCache>();
+
+   private ConcurrentMap<Long, PageSubscription> activeCursors = new ConcurrentHashMap<Long, PageSubscription>();
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public PageCursorProviderImpl(final PagingStore pagingStore,
+                                 final StorageManager storageManager,
+                                 final ExecutorFactory executorFactory)
+   {
+      this.pagingStore = pagingStore;
+      this.storageManager = storageManager;
+      this.executorFactory = executorFactory;
+      this.executor = executorFactory.getExecutor();
+   }
+
+   // Public --------------------------------------------------------
+
+   public PagingStore getAssociatedStore()
+   {
+      return pagingStore;
+   }
+
+   public synchronized PageSubscription createSubscription(long cursorID, Filter filter, boolean persistent)
+   {
+      PageSubscription activeCursor = activeCursors.get(cursorID);
+      if (activeCursor != null)
+      {
+         throw new IllegalStateException("Cursor " + cursorID + " had already been created");
+      }
+
+      activeCursor = new PageSubscriptionImpl(this,
+                                        pagingStore,
+                                        storageManager,
+                                        executorFactory.getExecutor(),
+                                        filter,
+                                        cursorID,
+                                        persistent);
+      activeCursors.put(cursorID, activeCursor);
+      return activeCursor;
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCursorProvider#createCursor()
+    */
+   public synchronized PageSubscription getSubscription(long cursorID)
+   {
+      return activeCursors.get(cursorID);
+   }
+
+   public PagedMessage getMessage(final PagePosition pos) throws Exception
+   {
+      PageCache cache = getPageCache(pos);
+
+      if (pos.getMessageNr() >= cache.getNumberOfMessages())
+      {
+         // sanity check, this should never happen unless there's a bug
+         throw new IllegalStateException("Invalid messageNumber passed = " + pos);
+      }
+
+      return cache.getMessage(pos.getMessageNr());
+   }
+   
+   public PagedReference newReference(final PagePosition pos, final PagedMessage msg, final PageSubscription subscription)
+   {
+      return new PagedReferenceImpl(pos, msg, subscription);
+   }
+
+   /**
+    * No need to synchronize this method since the private getPageCache will have a synchronized call
+    */
+   public PageCache getPageCache(PagePosition pos)
+   {
+      PageCache cache = pos.getPageCache();
+      if (cache == null)
+      {
+         cache = getPageCache(pos.getPageNr());
+         pos.setPageCache(cache);
+      }
+      return cache;
+   }
+
+   public void addPageCache(PageCache cache)
+   {
+      synchronized (softCache)
+      {
+         softCache.put(cache.getPageId(), cache);
+      }
+   }
+
+   public int getCacheSize()
+   {
+      synchronized (softCache)
+      {
+         return softCache.size();
+      }
+   }
+
+   public void processReload() throws Exception
+   {
+      for (PageSubscription cursor : this.activeCursors.values())
+      {
+         cursor.processReload();
+      }
+
+      cleanup();
+
+   }
+
+   public void stop()
+   {
+      for (PageSubscription cursor : activeCursors.values())
+      {
+         cursor.stop();
+      }
+
+      Future future = new Future();
+
+      executor.execute(future);
+
+      while (!future.await(10000))
+      {
+         log.warn("Waiting cursor provider " + this + " to finish executors");
+      }
+
+   }
+
+   public void flushExecutors()
+   {
+      for (PageSubscription cursor : activeCursors.values())
+      {
+         cursor.flushExecutors();
+      }
+
+      Future future = new Future();
+
+      executor.execute(future);
+
+      while (!future.await(10000))
+      {
+         log.warn("Waiting cursor provider " + this + " to finish executors");
+      }
+
+   }
+
+   public void close(PageSubscription cursor)
+   {
+      activeCursors.remove(cursor.getId());
+
+      scheduleCleanup();
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCursorProvider#scheduleCleanup()
+    */
+   public void scheduleCleanup()
+   {
+
+      executor.execute(new Runnable()
+      {
+         public void run()
+         {
+            cleanup();
+         }
+      });
+   }
+
+   public void cleanup()
+   {
+      ArrayList<Page> depagedPages = new ArrayList<Page>();
+
+      pagingStore.lock();
+
+      synchronized (this)
+      {
+         try
+         {
+            if (!pagingStore.isStarted())
+            {
+               return;
+            }
+            
+            if (pagingStore.getNumberOfPages() == 0)
+            {
+               return;
+            }
+
+            ArrayList<PageSubscription> cursorList = new ArrayList<PageSubscription>();
+            cursorList.addAll(activeCursors.values());
+
+            long minPage = checkMinPage(cursorList);
+
+            if (minPage == pagingStore.getCurrentWritingPage() && pagingStore.getCurrentPage().getNumberOfMessages() > 0)
+            {
+               boolean complete = true;
+
+               for (PageSubscription cursor : cursorList)
+               {
+                  if (!cursor.isComplete(minPage))
+                  {
+                     complete = false;
+                     break;
+                  }
+               }
+
+               if (complete)
+               {
+
+                  System.out.println("Disabling depage!");
+                  pagingStore.forceAnotherPage();
+
+                  Page currentPage = pagingStore.getCurrentPage();
+
+                  try
+                  {
+                     // First step: Move every cursor to the next bookmarked page (that was just created)
+                     for (PageSubscription cursor : cursorList)
+                     {
+                        cursor.ack(new PagePositionImpl(currentPage.getPageId(), -1));
+                     }
+
+                     storageManager.waitOnOperations();
+                  }
+                  finally
+                  {
+                     for (PageSubscription cursor : cursorList)
+                     {
+                        cursor.enableAutoCleanup();
+                     }
+                  }
+
+                  pagingStore.stopPaging();
+
+                  // This has to be called after we stopped paging
+                  for (PageSubscription cursor : cursorList)
+                  {
+                     cursor.scheduleCleanupCheck();
+                  }
+
+               }
+            }
+
+            for (long i = pagingStore.getFirstPage(); i < minPage; i++)
+            {
+               Page page = pagingStore.depage();
+               if (page == null)
+               {
+                  break;
+               }
+               depagedPages.add(page);
+            }
+
+            if (pagingStore.getNumberOfPages() == 0 || pagingStore.getNumberOfPages() == 1 &&
+                pagingStore.getCurrentPage().getNumberOfMessages() == 0)
+            {
+               pagingStore.stopPaging();
+            }
+         }
+         catch (Exception ex)
+         {
+            log.warn("Couldn't complete cleanup on paging", ex);
+            return;
+         }
+         finally
+         {
+            pagingStore.unlock();
+         }
+      }
+
+      try
+      {
+         for (Page depagedPage : depagedPages)
+         {
+            depagedPage.delete();
+         }
+      }
+      catch (Exception ex)
+      {
+         log.warn("Couldn't complete cleanup on paging", ex);
+         return;
+      }
+
+   }
+
+   public void printDebug()
+   {
+      System.out.println("Debug information for PageCursorProviderImpl:");
+      for (PageCache cache : softCache.values())
+      {
+         System.out.println("Cache " + cache);
+      }
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   /* Protected as we may let test cases to instrument the test */
+   protected PageCacheImpl createPageCache(final long pageId) throws Exception
+   {
+      return new PageCacheImpl(pagingStore.createPage((int)pageId));
+   }
+
+   // Private -------------------------------------------------------
+
+   /**
+    * This method is synchronized because we want it to be atomic with the cursors being used
+    */
+   private long checkMinPage(List<PageSubscription> cursorList)
+   {
+      long minPage = Long.MAX_VALUE;
+
+      for (PageSubscription cursor : cursorList)
+      {
+         long firstPage = cursor.getFirstPage();
+         if (firstPage < minPage)
+         {
+            minPage = firstPage;
+         }
+      }
+
+      return minPage;
+
+   }
+
+   private PageCache getPageCache(final long pageId)
+   {
+      try
+      {
+         boolean needToRead = false;
+         PageCache cache = null;
+         synchronized (softCache)
+         {
+            if (pageId > pagingStore.getCurrentWritingPage())
+            {
+               return null;
+            }
+
+            cache = softCache.get(pageId);
+            if (cache == null)
+            {
+               cache = createPageCache(pageId);
+               needToRead = true;
+               // anyone reading from this cache will have to wait reading to finish first
+               // we also want only one thread reading this cache
+               cache.lock();
+               softCache.put(pageId, cache);
+            }
+         }
+
+         // Reading is done outside of the synchronized block, however
+         // the page stays locked until the entire reading is finished
+         if (needToRead)
+         {
+            Page page = null;
+            try
+            {
+               page = pagingStore.createPage((int)pageId);
+
+               page.open();
+
+               List<PagedMessage> pgdMessages = page.read();
+
+               for (PagedMessage pdgMessage : pgdMessages)
+               {
+                  pdgMessage.initMessage(storageManager);
+               }
+
+               cache.setMessages(pgdMessages.toArray(new PagedMessage[pgdMessages.size()]));
+
+            }
+            finally
+            {
+               try
+               {
+                  if (page != null)
+                  {
+                     page.close();
+                  }
+               }
+               catch (Throwable ignored)
+               {
+               }
+               cache.unlock();
+            }
+         }
+
+         return cache;
+      }
+      catch (Exception e)
+      {
+         throw new RuntimeException("Couldn't complete paging due to an IO Exception on Paging - " + e.getMessage(), e);
+      }
+   }
+
+   // Inner classes -------------------------------------------------
+
+}

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PagePositionImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PagePositionImpl.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PagePositionImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.paging.cursor.impl;
+
+import java.lang.ref.WeakReference;
+
+import org.hornetq.core.paging.cursor.PageCache;
+import org.hornetq.core.paging.cursor.PagePosition;
+
+/**
+ * A PagePosition
+ *
+ * @author <a href="mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class PagePositionImpl implements PagePosition
+{
+   private long pageNr;
+
+   private int messageNr;
+
+   /** ID used for storage */
+   private long recordID;
+   
+   private volatile WeakReference<PageCache> cacheReference;
+
+   /**
+    * @param pageNr
+    * @param messageNr
+    */
+   public PagePositionImpl(long pageNr, int messageNr)
+   {
+      super();
+      this.pageNr = pageNr;
+      this.messageNr = messageNr;
+   }
+
+   public PagePositionImpl(long pageNr, int messageNr, PageCache pageCache)
+   {
+      this(pageNr, messageNr);
+      this.setPageCache(pageCache);
+   }
+
+   /**
+    * @param pageNr
+    * @param messageNr
+    */
+   public PagePositionImpl()
+   {
+      
+   }
+
+   /**
+    * The cached page associaed with this position
+    * @return
+    */
+   public PageCache getPageCache()
+   {
+      if (cacheReference == null)
+      {
+         return null;
+      }
+      else
+      {
+         return cacheReference.get();
+      }
+   }
+   
+   public void setPageCache(final PageCache cache)
+   {
+      if (cache != null)
+      {
+         this.cacheReference = new WeakReference<PageCache>(cache);
+      }
+   }
+
+
+   /**
+    * @return the recordID
+    */
+   public long getRecordID()
+   {
+      return recordID;
+   }
+
+   /**
+    * @param recordID the recordID to set
+    */
+   public void setRecordID(long recordID)
+   {
+      this.recordID = recordID;
+   }
+
+   /**
+    * @return the pageNr
+    */
+   public long getPageNr()
+   {
+      return pageNr;
+   }
+
+   /**
+    * @return the messageNr
+    */
+   public int getMessageNr()
+   {
+      return messageNr;
+   }
+   
+   public boolean isRightAfter(final PagePosition previous)
+   {
+      return this.pageNr == previous.getPageNr() && this.messageNr == previous.getMessageNr() + 1;
+   }
+
+   /* (non-Javadoc)
+    * @see java.lang.Comparable#compareTo(java.lang.Object)
+    */
+   public int compareTo(PagePosition o)
+   {
+      if (pageNr > o.getPageNr())
+      {
+         return 1;
+      }
+      else if (pageNr < o.getPageNr())
+      {
+         return -1;
+      }
+      else if (recordID > o.getRecordID())
+      {
+         return 1;
+      }
+      else if (recordID < o.getRecordID())
+      {
+         return -1;
+      }
+      else
+      {
+         return 0;
+      }
+   }
+
+   public PagePosition nextMessage()
+   {
+      return new PagePositionImpl(this.pageNr, this.messageNr + 1, this.getPageCache());
+   }
+
+   public PagePosition nextPage()
+   {
+      return new PagePositionImpl(this.pageNr + 1, 0);
+   }
+
+   public boolean isNextSequenceOf(PagePosition pos)
+   {
+      return this.pageNr == pos.getPageNr() && this.getRecordID() - pos.getRecordID() == 1;
+   }
+
+   /* (non-Javadoc)
+    * @see java.lang.Object#hashCode()
+    */
+   @Override
+   public int hashCode()
+   {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + messageNr;
+      result = prime * result + (int)(pageNr ^ (pageNr >>> 32));
+      return result;
+   }
+
+   /* (non-Javadoc)
+    * @see java.lang.Object#equals(java.lang.Object)
+    */
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      PagePositionImpl other = (PagePositionImpl)obj;
+      if (messageNr != other.messageNr)
+         return false;
+      if (pageNr != other.pageNr)
+         return false;
+      return true;
+   }
+   
+   @Override
+   public String toString()
+   {
+      return "PagePositionImpl [pageNr=" + pageNr + ", messageNr=" + messageNr + ", recordID=" + recordID + "]";
+   }
+
+
+   
+}

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PageSubscriptionImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PageSubscriptionImpl.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/cursor/impl/PageSubscriptionImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,1201 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.paging.cursor.impl;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.hornetq.core.filter.Filter;
+import org.hornetq.core.journal.IOAsyncTask;
+import org.hornetq.core.logging.Logger;
+import org.hornetq.core.paging.PageTransactionInfo;
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.paging.PagingStore;
+import org.hornetq.core.paging.cursor.PageCache;
+import org.hornetq.core.paging.cursor.PageCursorProvider;
+import org.hornetq.core.paging.cursor.PagePosition;
+import org.hornetq.core.paging.cursor.PageSubscription;
+import org.hornetq.core.paging.cursor.PagedReference;
+import org.hornetq.core.persistence.StorageManager;
+import org.hornetq.core.server.MessageReference;
+import org.hornetq.core.server.Queue;
+import org.hornetq.core.server.ServerMessage;
+import org.hornetq.core.transaction.Transaction;
+import org.hornetq.core.transaction.TransactionOperationAbstract;
+import org.hornetq.core.transaction.TransactionPropertyIndexes;
+import org.hornetq.core.transaction.impl.TransactionImpl;
+import org.hornetq.utils.ConcurrentHashSet;
+import org.hornetq.utils.Future;
+import org.hornetq.utils.LinkedListIterator;
+
+/**
+ * A PageCursorImpl
+ *
+ * A page cursor will always store its 
+ * @author <a href="mailto:clebert.suconic at jboss.com">Clebert Suconic</a>
+ *
+ * 
+ */
+public class PageSubscriptionImpl implements PageSubscription
+{
+   // Constants -----------------------------------------------------
+   private static final Logger log = Logger.getLogger(PageSubscriptionImpl.class);
+
+   // Attributes ----------------------------------------------------
+
+   private final boolean isTrace = false; // PageCursorImpl.log.isTraceEnabled();
+
+   private static void trace(final String message)
+   {
+      // PageCursorImpl.log.info(message);
+      System.out.println(message);
+   }
+
+   private volatile boolean autoCleanup = true;
+
+   private final StorageManager store;
+
+   private final long cursorId;
+
+   private Queue queue;
+
+   private final boolean persistent;
+
+   private final Filter filter;
+
+   private final PagingStore pageStore;
+
+   private final PageCursorProvider cursorProvider;
+
+   private final Executor executor;
+
+   private volatile PagePosition lastAckedPosition;
+
+   private List<PagePosition> recoveredACK;
+
+   private final SortedMap<Long, PageCursorInfo> consumedPages = Collections.synchronizedSortedMap(new TreeMap<Long, PageCursorInfo>());
+
+   // We only store the position for redeliveries. They will be read from the SoftCache again during delivery.
+   private final ConcurrentLinkedQueue<PagePosition> redeliveries = new ConcurrentLinkedQueue<PagePosition>();
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public PageSubscriptionImpl(final PageCursorProvider cursorProvider,
+                               final PagingStore pageStore,
+                               final StorageManager store,
+                               final Executor executor,
+                               final Filter filter,
+                               final long cursorId,
+                               final boolean persistent)
+   {
+      this.pageStore = pageStore;
+      this.store = store;
+      this.cursorProvider = cursorProvider;
+      this.cursorId = cursorId;
+      this.executor = executor;
+      this.filter = filter;
+      this.persistent = persistent;
+   }
+
+   // Public --------------------------------------------------------
+
+   public Queue getQueue()
+   {
+      return queue;
+   }
+
+   public boolean isPaging()
+   {
+      return pageStore.isPaging();
+   }
+
+   public void setQueue(Queue queue)
+   {
+      this.queue = queue;
+   }
+
+   public void disableAutoCleanup()
+   {
+      autoCleanup = false;
+   }
+
+   public void enableAutoCleanup()
+   {
+      autoCleanup = true;
+   }
+
+   public PageCursorProvider getProvider()
+   {
+      return cursorProvider;
+   }
+
+   public void bookmark(PagePosition position) throws Exception
+   {
+      PageCursorInfo cursorInfo = getPageInfo(position);
+
+      if (position.getMessageNr() > 0)
+      {
+         cursorInfo.confirmed.addAndGet(position.getMessageNr());
+      }
+
+      ack(position);
+   }
+
+   public void scheduleCleanupCheck()
+   {
+      if (autoCleanup)
+      {
+         executor.execute(new Runnable()
+         {
+
+            public void run()
+            {
+               try
+               {
+                  cleanupEntries();
+               }
+               catch (Exception e)
+               {
+                  PageSubscriptionImpl.log.warn("Error on cleaning up cursor pages", e);
+               }
+            }
+         });
+      }
+   }
+
+   /** 
+    * It will cleanup all the records for completed pages
+    * */
+   public void cleanupEntries() throws Exception
+   {
+      Transaction tx = new TransactionImpl(store);
+
+      boolean persist = false;
+
+      final ArrayList<PageCursorInfo> completedPages = new ArrayList<PageCursorInfo>();
+
+      // First get the completed pages using a lock
+      synchronized (this)
+      {
+         for (Entry<Long, PageCursorInfo> entry : consumedPages.entrySet())
+         {
+            PageCursorInfo info = entry.getValue();
+            if (info.isDone() && !info.isPendingDelete() && lastAckedPosition != null)
+            {
+               if (entry.getKey() == lastAckedPosition.getPageNr())
+               {
+                  // PageSubscriptionImpl.trace("We can't clear page " + entry.getKey() +
+                  // " now since it's the current page");
+               }
+               else
+               {
+                  info.setPendingDelete();
+                  completedPages.add(entry.getValue());
+               }
+            }
+         }
+      }
+
+      for (int i = 0; i < completedPages.size(); i++)
+      {
+         PageCursorInfo info = completedPages.get(i);
+
+         for (PagePosition pos : info.acks)
+         {
+            if (pos.getRecordID() > 0)
+            {
+               store.deleteCursorAcknowledgeTransactional(tx.getID(), pos.getRecordID());
+               if (!persist)
+               {
+                  // only need to set it once
+                  tx.setContainsPersistent();
+                  persist = true;
+               }
+            }
+         }
+      }
+
+      tx.addOperation(new TransactionOperationAbstract()
+      {
+
+         @Override
+         public void afterCommit(final Transaction tx)
+         {
+            executor.execute(new Runnable()
+            {
+
+               public void run()
+               {
+                  synchronized (PageSubscriptionImpl.this)
+                  {
+                     for (PageCursorInfo completePage : completedPages)
+                     {
+                        if (isTrace)
+                        {
+                           PageSubscriptionImpl.trace("Removing page " + completePage.getPageId());
+                        }
+                        if (consumedPages.remove(completePage.getPageId()) == null)
+                        {
+                           PageSubscriptionImpl.log.warn("Couldn't remove page " + completePage.getPageId() +
+                                                         " from consumed pages on cursor for address " +
+                                                         pageStore.getAddress());
+                        }
+                     }
+                  }
+
+                  cursorProvider.scheduleCleanup();
+               }
+            });
+         }
+      });
+
+      tx.commit();
+
+   }
+
+   private PagedReference getReference(PagePosition pos) throws Exception
+   {
+      return cursorProvider.newReference(pos, cursorProvider.getMessage(pos), this);
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCursor#iterator()
+    */
+   public LinkedListIterator<PagedReference> iterator()
+   {
+      return new CursorIterator();
+   }
+
+   private PagedReference internalGetNext(final PagePosition pos)
+   {
+      PagePosition retPos = pos.nextMessage();
+
+      PageCache cache = cursorProvider.getPageCache(pos);
+
+      if (cache == null)
+      {
+         return null;
+      }
+
+      if (!cache.isLive() && retPos.getMessageNr() >= cache.getNumberOfMessages())
+      {
+         retPos = pos.nextPage();
+
+         cache = cursorProvider.getPageCache(retPos);
+
+         if (cache == null)
+         {
+            return null;
+         }
+
+         if (retPos.getMessageNr() >= cache.getNumberOfMessages())
+         {
+            return null;
+         }
+      }
+
+      PagedMessage serverMessage = cache.getMessage(retPos.getMessageNr());
+
+      if (serverMessage != null)
+      {
+         return cursorProvider.newReference(retPos, serverMessage, this);
+      }
+      else
+      {
+         return null;
+      }
+   }
+
+   private boolean routed(PagedMessage message)
+   {
+      long id = getId();
+
+      for (long qid : message.getQueueIDs())
+      {
+         if (qid == id)
+         {
+            return true;
+         }
+      }
+      return false;
+   }
+
+   /**
+    * 
+    */
+   private synchronized PagePosition getStartPosition()
+   {
+      // Get the first page not marked for deletion
+      // It's important to verify if it's not marked for deletion as you may have a pending request on the queue
+      for (Map.Entry<Long, PageCursorInfo> entry : consumedPages.entrySet())
+      {
+         if (!entry.getValue().isPendingDelete())
+         {
+            if (entry.getValue().acks.isEmpty())
+            {
+               return new PagePositionImpl(entry.getKey(), -1);
+            }
+            else
+            {
+               // The list is not ordered...
+               // This is only done at creation of the queue, so we just scan instead of keeping the list ordened
+               PagePosition retValue = null;
+
+               for (PagePosition pos : entry.getValue().acks)
+               {
+                  System.out.println("Analizing " + pos);
+                  if (retValue == null || retValue.getMessageNr() > pos.getMessageNr())
+                  {
+                     retValue = pos;
+                  }
+               }
+
+               System.out.println("Returning initial position " + retValue);
+
+               return retValue;
+            }
+         }
+      }
+
+      return new PagePositionImpl(pageStore.getFirstPage(), -1);
+   }
+
+   public void ackTx(final Transaction tx, final PagePosition position) throws Exception
+   {
+      // if the cursor is persistent
+      if (persistent)
+      {
+         store.storeCursorAcknowledgeTransactional(tx.getID(), cursorId, position);
+      }
+      installTXCallback(tx, position);
+
+   }
+
+   public void ackTx(final Transaction tx, final PagedReference reference) throws Exception
+   {
+      ackTx(tx, reference.getPosition());
+
+      PageTransactionInfo txInfo = getPageTransaction(reference);
+      if (txInfo != null)
+      {
+         txInfo.storeUpdate(store, pageStore.getPagingManager(), tx);
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCursor#confirm(org.hornetq.core.paging.cursor.PagePosition)
+    */
+   public void ack(final PagedReference reference) throws Exception
+   {
+      ack(reference.getPosition());
+      PageTransactionInfo txInfo = getPageTransaction(reference);
+      if (txInfo != null)
+      {
+         txInfo.storeUpdate(this.store, pageStore.getPagingManager());
+      }
+   }
+
+   public void ack(final PagePosition position) throws Exception
+   {
+      // if we are dealing with a persistent cursor
+      if (persistent)
+      {
+         store.storeCursorAcknowledge(cursorId, position);
+      }
+
+      store.afterCompleteOperations(new IOAsyncTask()
+      {
+
+         public void onError(final int errorCode, final String errorMessage)
+         {
+         }
+
+         public void done()
+         {
+            processACK(position);
+         }
+      });
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCursor#getFirstPage()
+    */
+   public long getFirstPage()
+   {
+      if (consumedPages.isEmpty())
+      {
+         return 0;
+      }
+      else
+      {
+         return consumedPages.firstKey();
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCursor#returnElement(org.hornetq.core.paging.cursor.PagePosition)
+    */
+   public void redeliver(final PagePosition position)
+   {
+      synchronized (redeliveries)
+      {
+         redeliveries.add(position);
+      }
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageSubscription#queryMessage(org.hornetq.core.paging.cursor.PagePosition)
+    */
+   public PagedMessage queryMessage(PagePosition pos)
+   {
+      try
+      {
+         return cursorProvider.getMessage(pos);
+      }
+      catch (Exception e)
+      {
+         throw new RuntimeException(e.getMessage(), e);
+      }
+   }
+
+   /** 
+    * Theres no need to synchronize this method as it's only called from journal load on startup
+    */
+   public void reloadACK(final PagePosition position)
+   {
+      if (recoveredACK == null)
+      {
+         recoveredACK = new LinkedList<PagePosition>();
+      }
+
+      recoveredACK.add(position);
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCursor#recoverPreparedACK(org.hornetq.core.paging.cursor.PagePosition)
+    */
+   public void reloadPreparedACK(final Transaction tx, final PagePosition position)
+   {
+      installTXCallback(tx, position);
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCursor#positionIgnored(org.hornetq.core.paging.cursor.PagePosition)
+    */
+   public void positionIgnored(final PagePosition position)
+   {
+      processACK(position);
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCursor#isComplete(long)
+    */
+   public boolean isComplete(long page)
+   {
+      PageCursorInfo info = consumedPages.get(page);
+      return info != null && info.isDone();
+   }
+
+   /**
+    * All the data associated with the cursor should go away here
+    */
+   public void close() throws Exception
+   {
+      final long tx = store.generateUniqueID();
+
+      final ArrayList<Exception> ex = new ArrayList<Exception>();
+
+      final AtomicBoolean isPersistent = new AtomicBoolean(false);
+
+      // We can't delete the records at the caller's thread
+      // because an executor may be holding the synchronized on PageCursorImpl
+      // what would lead to a dead lock
+      // so, we delete it inside the executor also
+      // and wait for the result
+      // The caller will be treating eventual IO exceptions and dispatching to the original thread's caller
+      executor.execute(new Runnable()
+      {
+
+         public void run()
+         {
+            try
+            {
+               synchronized (PageSubscriptionImpl.this)
+               {
+                  for (PageCursorInfo cursor : consumedPages.values())
+                  {
+                     for (PagePosition info : cursor.acks)
+                     {
+                        if (info.getRecordID() != 0)
+                        {
+                           isPersistent.set(true);
+                           store.deleteCursorAcknowledgeTransactional(tx, info.getRecordID());
+                        }
+                     }
+                  }
+               }
+            }
+            catch (Exception e)
+            {
+               ex.add(e);
+               PageSubscriptionImpl.log.warn(e.getMessage(), e);
+            }
+         }
+      });
+
+      Future future = new Future();
+
+      executor.execute(future);
+
+      while (!future.await(5000))
+      {
+         PageSubscriptionImpl.log.warn("Timeout on waiting cursor " + this + " to be closed");
+      }
+
+      if (isPersistent.get())
+      {
+         // Another reason to perform the commit at the main thread is because the OperationContext may only send the
+         // result to the client when
+         // the IO on commit is done
+         if (ex.size() == 0)
+         {
+            store.commit(tx);
+         }
+         else
+         {
+            store.rollback(tx);
+            throw ex.get(0);
+         }
+      }
+
+      cursorProvider.close(this);
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.cursor.PageCursor#getId()
+    */
+   public long getId()
+   {
+      return cursorId;
+   }
+
+   public boolean isPersistent()
+   {
+      return persistent;
+   }
+
+   public void processReload() throws Exception
+   {
+      if (recoveredACK != null)
+      {
+         if (isTrace)
+         {
+            PageSubscriptionImpl.trace("********** processing reload!!!!!!!");
+         }
+         Collections.sort(recoveredACK);
+
+         boolean first = true;
+
+         for (PagePosition pos : recoveredACK)
+         {
+            lastAckedPosition = pos;
+            PageCursorInfo positions = getPageInfo(pos);
+            if (first)
+            {
+               first = false;
+               if (pos.getMessageNr() > 0)
+               {
+                  positions.confirmed.addAndGet(pos.getMessageNr());
+               }
+            }
+
+            positions.addACK(pos);
+         }
+
+         recoveredACK.clear();
+         recoveredACK = null;
+      }
+   }
+
+   public void flushExecutors()
+   {
+      Future future = new Future();
+      executor.execute(future);
+      while (!future.await(1000))
+      {
+         PageSubscriptionImpl.log.warn("Waiting page cursor to finish executors - " + this);
+      }
+   }
+
+   public void stop()
+   {
+      flushExecutors();
+   }
+
+   public void printDebug()
+   {
+      printDebug(toString());
+   }
+
+   public void printDebug(final String msg)
+   {
+      System.out.println("Debug information on PageCurorImpl- " + msg);
+      for (PageCursorInfo info : consumedPages.values())
+      {
+         System.out.println(info);
+      }
+   }
+
+   private synchronized PageCursorInfo getPageInfo(final PagePosition pos)
+   {
+      return getPageInfo(pos, true);
+   }
+
+   /**
+    * @param page
+    * @return
+    */
+   private synchronized PageCursorInfo getPageInfo(final PagePosition pos, boolean create)
+   {
+      PageCursorInfo pageInfo = consumedPages.get(pos.getPageNr());
+
+      if (create && pageInfo == null)
+      {
+         PageCache cache = cursorProvider.getPageCache(pos);
+         pageInfo = new PageCursorInfo(pos.getPageNr(), cache.getNumberOfMessages(), cache);
+         consumedPages.put(pos.getPageNr(), pageInfo);
+      }
+
+      return pageInfo;
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   protected boolean match(final ServerMessage message)
+   {
+      if (filter == null)
+      {
+         return true;
+      }
+      else
+      {
+         return filter.match(message);
+      }
+   }
+
+   // Private -------------------------------------------------------
+
+   // To be called only after the ACK has been processed and guaranteed to be on storae
+   // The only exception is on non storage events such as not matching messages
+   private void processACK(final PagePosition pos)
+   {
+      if (lastAckedPosition == null || pos.compareTo(lastAckedPosition) > 0)
+      {
+         if (lastAckedPosition != null && lastAckedPosition.getPageNr() != pos.getPageNr())
+         {
+            // there's a different page being acked, we will do the check right away
+            if (autoCleanup)
+            {
+               scheduleCleanupCheck();
+            }
+         }
+         lastAckedPosition = pos;
+      }
+      PageCursorInfo info = getPageInfo(pos);
+
+      info.addACK(pos);
+   }
+
+   /**
+    * @param tx
+    * @param position
+    */
+   private void installTXCallback(final Transaction tx, final PagePosition position)
+   {
+      if (position.getRecordID() > 0)
+      {
+         // It needs to persist, otherwise the cursor will return to the fist page position
+         tx.setContainsPersistent();
+      }
+
+      PageCursorTX cursorTX = (PageCursorTX)tx.getProperty(TransactionPropertyIndexes.PAGE_CURSOR_POSITIONS);
+
+      if (cursorTX == null)
+      {
+         cursorTX = new PageCursorTX();
+         tx.putProperty(TransactionPropertyIndexes.PAGE_CURSOR_POSITIONS, cursorTX);
+         tx.addOperation(cursorTX);
+      }
+
+      cursorTX.addPositionConfirmation(this, position);
+
+   }
+
+   private PageTransactionInfo getPageTransaction(final PagedReference reference)
+   {
+      if (reference.getPagedMessage().getTransactionID() != 0)
+      {
+         return pageStore.getPagingManager().getTransaction(reference.getPagedMessage().getTransactionID());
+      }
+      else
+      {
+         return null;
+      }
+   }
+
+   /**
+    *  A callback from the PageCursorInfo. It will be called when all the messages on a page have been acked
+    * @param info
+    */
+   private void onPageDone(final PageCursorInfo info)
+   {
+      if (autoCleanup)
+      {
+         scheduleCleanupCheck();
+      }
+   }
+
+   // Inner classes -------------------------------------------------
+
+   /** 
+    * This will hold information about the pending ACKs towards a page.
+    * This instance will be released as soon as the entire page is consumed, releasing the memory at that point
+    * The ref counts are increased also when a message is ignored for any reason.
+    * */
+   private class PageCursorInfo
+   {
+      // Number of messages existent on this page
+      private final int numberOfMessages;
+
+      private final long pageId;
+
+      // Confirmed ACKs on this page
+      private final List<PagePosition> acks = Collections.synchronizedList(new LinkedList<PagePosition>());
+
+      private WeakReference<PageCache> cache;
+
+      private Set<PagePosition> removedReferences = new ConcurrentHashSet<PagePosition>();
+
+      // The page was live at the time of the creation
+      private final boolean wasLive;
+
+      // There's a pending delete on the async IO pipe
+      // We're holding this object to avoid delete the pages before the IO is complete,
+      // however we can't delete these records again
+      private boolean pendingDelete;
+
+      // We need a separate counter as the cursor may be ignoring certain values because of incomplete transactions or
+      // expressions
+      private final AtomicInteger confirmed = new AtomicInteger(0);
+
+      @Override
+      public String toString()
+      {
+         return "PageCursorInfo::PageID=" + pageId +
+                " numberOfMessage = " +
+                numberOfMessages +
+                ", confirmed = " +
+                confirmed;
+      }
+
+      public PageCursorInfo(final long pageId, final int numberOfMessages, final PageCache cache)
+      {
+         this.pageId = pageId;
+         this.numberOfMessages = numberOfMessages;
+         wasLive = cache.isLive();
+         if (wasLive)
+         {
+            this.cache = new WeakReference<PageCache>(cache);
+         }
+      }
+
+      public boolean isDone()
+      {
+         return getNumberOfMessages() == confirmed.get();
+      }
+
+      public boolean isPendingDelete()
+      {
+         return pendingDelete;
+      }
+
+      public void setPendingDelete()
+      {
+         pendingDelete = true;
+      }
+
+      /**
+       * @return the pageId
+       */
+      public long getPageId()
+      {
+         return pageId;
+      }
+
+      public boolean isRemoved(final PagePosition pos)
+      {
+         return removedReferences.contains(pos);
+      }
+
+      public void remove(final PagePosition position)
+      {
+         removedReferences.add(position);
+      }
+
+      public void addACK(final PagePosition posACK)
+      {
+         removedReferences.add(posACK);
+         acks.add(posACK);
+
+         if (isTrace)
+         {
+            PageSubscriptionImpl.trace("numberOfMessages =  " + getNumberOfMessages() +
+                                       " confirmed =  " +
+                                       (confirmed.get() + 1) +
+                                       ", page = " +
+                                       pageId);
+         }
+
+         // Negative could mean a bookmark on the first element for the page (example -1)
+         if (posACK.getMessageNr() >= 0)
+         {
+            if (getNumberOfMessages() == confirmed.incrementAndGet())
+            {
+               onPageDone(this);
+            }
+         }
+      }
+
+      private int getNumberOfMessages()
+      {
+         if (wasLive)
+         {
+            PageCache cache = this.cache.get();
+            if (cache != null)
+            {
+               return cache.getNumberOfMessages();
+            }
+            else
+            {
+               cache = cursorProvider.getPageCache(new PagePositionImpl(pageId, 0));
+               this.cache = new WeakReference<PageCache>(cache);
+               return cache.getNumberOfMessages();
+            }
+         }
+         else
+         {
+            return numberOfMessages;
+         }
+      }
+
+   }
+
+   static class PageCursorTX extends TransactionOperationAbstract
+   {
+      HashMap<PageSubscriptionImpl, List<PagePosition>> pendingPositions = new HashMap<PageSubscriptionImpl, List<PagePosition>>();
+
+      public void addPositionConfirmation(final PageSubscriptionImpl cursor, final PagePosition position)
+      {
+         List<PagePosition> list = pendingPositions.get(cursor);
+
+         if (list == null)
+         {
+            list = new LinkedList<PagePosition>();
+            pendingPositions.put(cursor, list);
+         }
+
+         list.add(position);
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.transaction.TransactionOperation#afterCommit(org.hornetq.core.transaction.Transaction)
+       */
+      @Override
+      public void afterCommit(final Transaction tx)
+      {
+         for (Entry<PageSubscriptionImpl, List<PagePosition>> entry : pendingPositions.entrySet())
+         {
+            PageSubscriptionImpl cursor = entry.getKey();
+
+            List<PagePosition> positions = entry.getValue();
+
+            for (PagePosition confirmed : positions)
+            {
+               cursor.processACK(confirmed);
+            }
+
+         }
+      }
+      
+      /* (non-Javadoc)
+       * @see org.hornetq.core.transaction.TransactionOperation#getRelatedMessageReferences()
+       */
+      public List<MessageReference> getRelatedMessageReferences()
+      {
+         return Collections.emptyList();
+      }
+      
+
+   }
+
+   class CursorIterator implements LinkedListIterator<PagedReference>
+   {
+      private PagePosition position = null;
+
+      private PagePosition lastOperation = null;
+
+      private volatile boolean isredelivery = false;
+
+      private volatile PagedReference lastRedelivery = null;
+
+      /** next element taken on hasNext test.
+       *  it has to be delivered on next next operation */
+      private volatile PagedReference cachedNext;
+
+      public CursorIterator()
+      {
+      }
+
+      public void repeat()
+      {
+         if (isredelivery)
+         {
+            synchronized (redeliveries)
+            {
+               cachedNext = lastRedelivery;
+            }
+         }
+         else
+         {
+            if (lastOperation == null)
+            {
+               position = null;
+            }
+            else
+            {
+               position = lastOperation;
+            }
+         }
+      }
+
+      /* (non-Javadoc)
+       * @see java.util.Iterator#next()
+       */
+      public synchronized PagedReference next()
+      {
+
+         if (cachedNext != null)
+         {
+            PagedReference retPos = cachedNext;
+            cachedNext = null;
+            return retPos;
+         }
+
+         try
+         {
+            if (position == null)
+            {
+               position = getStartPosition();
+            }
+
+            return moveNext();
+         }
+         catch (Exception e)
+         {
+            throw new RuntimeException(e.getMessage(), e);
+         }
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.paging.cursor.PageCursor#moveNext()
+       */
+      public PagedReference moveNext() throws Exception
+      {
+         synchronized (PageSubscriptionImpl.this)
+         {
+            boolean match = false;
+
+            PagedReference message = null;
+
+            PagePosition lastPosition = position;
+            PagePosition tmpPosition = position;
+
+            do
+            {
+               synchronized (redeliveries)
+               {
+                  PagePosition redelivery = redeliveries.poll();
+
+                  if (redelivery != null)
+                  {
+                     // There's a redelivery pending, we will get it out of that pool instead
+                     isredelivery = true;
+                     PagedReference redeliveredMsg = getReference(redelivery);
+                     lastRedelivery = redeliveredMsg;
+
+                     return redeliveredMsg;
+                  }
+                  else
+                  {
+                     lastRedelivery = null;
+                     isredelivery = false;
+                  }
+
+                  message = internalGetNext(tmpPosition);
+               }
+
+               if (message == null)
+               {
+                  break;
+               }
+
+               tmpPosition = message.getPosition();
+
+               boolean valid = true;
+               boolean ignored = false;
+
+               // Validate the scenarios where the message should be considered not valid even to be considered
+
+               // 1st... is it routed?
+
+               valid = routed(message.getPagedMessage());
+               if (!valid)
+               {
+                  ignored = true;
+               }
+
+               // 2nd ... if TX, is it committed?
+               if (valid && message.getPagedMessage().getTransactionID() != 0)
+               {
+                  PageTransactionInfo tx = pageStore.getPagingManager().getTransaction(message.getPagedMessage()
+                                                                                              .getTransactionID());
+                  if (tx == null)
+                  {
+                     log.warn("Couldn't locate page transaction " + message.getPagedMessage().getTransactionID() +
+                              ", ignoring message on position " +
+                              message.getPosition());
+                     valid = false;
+                     ignored = true;
+                  }
+                  else
+                  {
+                     if (tx.deliverAfterCommit(PageSubscriptionImpl.this, message.getPosition()))
+                     {
+                        valid = false;
+                        ignored = false;
+                     }
+                  }
+               }
+
+               // 3rd... was it previously removed?
+               if (valid)
+               {
+                  // We don't create a PageCursorInfo unless we are doing a write operation (ack or removing)
+                  // Say you have a Browser that will only read the files... there's no need to control PageCursors is
+                  // nothing
+                  // is being changed. That's why the false is passed as a parameter here
+                  PageCursorInfo info = getPageInfo(message.getPosition(), false);
+                  if (info != null && info.isRemoved(message.getPosition()))
+                  {
+                     valid = false;
+                  }
+               }
+
+               if (!ignored)
+               {
+                  position = message.getPosition();
+               }
+
+               if (valid)
+               {
+                  match = match(message.getMessage());
+
+                  if (!match)
+                  {
+                     processACK(message.getPosition());
+                  }
+               }
+               else if (ignored)
+               {
+                  positionIgnored(message.getPosition());
+               }
+            }
+            while (message != null && !match);
+
+            if (message != null)
+            {
+               lastOperation = lastPosition;
+            }
+
+            return message;
+         }
+      }
+
+      /** QueueImpl::deliver could be calling hasNext while QueueImpl.depage could be using next and hasNext as well. 
+       *  It would be a rare race condition but I would prefer avoiding that scenario */
+      public synchronized boolean hasNext()
+      {
+         // if an unbehaved program called hasNext twice before next, we only cache it once.
+         if (cachedNext != null)
+         {
+            return true;
+         }
+
+         if (!pageStore.isPaging())
+         {
+            return false;
+         }
+
+         cachedNext = next();
+
+         return cachedNext != null;
+      }
+
+      /* (non-Javadoc)
+       * @see java.util.Iterator#remove()
+       */
+      public void remove()
+      {
+         if (!isredelivery)
+         {
+            PageSubscriptionImpl.this.getPageInfo(position).remove(position);
+         }
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.utils.LinkedListIterator#close()
+       */
+      public void close()
+      {
+      }
+   }
+
+}

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PageImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PageImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PageImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -13,7 +13,6 @@
 
 package org.hornetq.core.paging.impl;
 
-import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
@@ -27,6 +26,7 @@
 import org.hornetq.core.logging.Logger;
 import org.hornetq.core.paging.Page;
 import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.paging.cursor.LivePageCache;
 import org.hornetq.core.persistence.StorageManager;
 import org.hornetq.utils.DataConstants;
 
@@ -35,7 +35,7 @@
  * @author <a href="mailto:clebert.suconic at jboss.com">Clebert Suconic</a>
  *
  */
-public class PageImpl implements Page
+public class PageImpl implements Page, Comparable<Page>
 {
    // Constants -----------------------------------------------------
 
@@ -58,6 +58,11 @@
    private final SequentialFile file;
 
    private final SequentialFileFactory fileFactory;
+   
+   /**
+    * The page cache that will be filled with data as we write more data
+    */
+   private volatile LivePageCache pageCache;
 
    private final AtomicInteger size = new AtomicInteger(0);
 
@@ -90,13 +95,19 @@
    {
       return pageId;
    }
+   
+   public void setLiveCache(LivePageCache pageCache)
+   {
+      this.pageCache = pageCache;
+   }
 
    public List<PagedMessage> read() throws Exception
    {
       ArrayList<PagedMessage> messages = new ArrayList<PagedMessage>();
 
+      size.set((int)file.size());
       // Using direct buffer, as described on https://jira.jboss.org/browse/HORNETQ-467
-      ByteBuffer buffer2 = ByteBuffer.allocateDirect((int)file.size());
+      ByteBuffer buffer2 = ByteBuffer.allocateDirect(size.get());
       
       file.position(0);
       file.read(buffer2);
@@ -168,6 +179,11 @@
       buffer.rewind();
 
       file.writeDirect(buffer, false);
+      
+      if (pageCache != null)
+      {
+         pageCache.addLiveMessage(message);
+      }
 
       numberOfMessages.incrementAndGet();
       size.addAndGet(buffer.limit());
@@ -193,6 +209,12 @@
       {
          storageManager.pageClosed(storeName, pageId);
       }
+      if (pageCache != null)
+      {
+         pageCache.close();
+         // leave it to the soft cache to decide when to release it now
+         pageCache = null;
+      }
       file.close();
    }
 
@@ -241,13 +263,54 @@
    {
       return "PageImpl::pageID="  + this.pageId + ", file=" + this.file;
    }
+   
 
+   /* (non-Javadoc)
+    * @see java.lang.Comparable#compareTo(java.lang.Object)
+    */
+   public int compareTo(Page otherPage)
+   {
+      return otherPage.getPageId() - this.pageId;
+   }
+
+
+   /* (non-Javadoc)
+    * @see java.lang.Object#hashCode()
+    */
+   @Override
+   public int hashCode()
+   {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + pageId;
+      return result;
+   }
+
+
    // Package protected ---------------------------------------------
 
    // Protected -----------------------------------------------------
 
    // Private -------------------------------------------------------
 
+   /* (non-Javadoc)
+    * @see java.lang.Object#equals(java.lang.Object)
+    */
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (this == obj)
+         return true;
+      if (obj == null)
+         return false;
+      if (getClass() != obj.getClass())
+         return false;
+      PageImpl other = (PageImpl)obj;
+      if (pageId != other.pageId)
+         return false;
+      return true;
+   }
+
    /**
     * @param position
     * @param msgNumber

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PageTransactionInfoImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PageTransactionInfoImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PageTransactionInfoImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -13,19 +13,25 @@
 
 package org.hornetq.core.paging.impl;
 
+import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.hornetq.api.core.HornetQBuffer;
+import org.hornetq.api.core.Pair;
+import org.hornetq.core.journal.IOAsyncTask;
 import org.hornetq.core.logging.Logger;
 import org.hornetq.core.paging.PageTransactionInfo;
 import org.hornetq.core.paging.PagingManager;
+import org.hornetq.core.paging.cursor.PagePosition;
+import org.hornetq.core.paging.cursor.PageSubscription;
 import org.hornetq.core.persistence.StorageManager;
 import org.hornetq.core.server.MessageReference;
 import org.hornetq.core.transaction.Transaction;
-import org.hornetq.core.transaction.TransactionOperation;
+import org.hornetq.core.transaction.TransactionOperationAbstract;
+import org.hornetq.core.transaction.TransactionPropertyIndexes;
 import org.hornetq.utils.DataConstants;
 
 /**
@@ -45,13 +51,15 @@
 
    private volatile long recordID = -1;
 
-   private volatile CountDownLatch countDownCompleted;
+   private volatile boolean committed = false;
+   
+   private volatile boolean useRedelivery = false;
 
-   private volatile boolean committed;
+   private volatile boolean rolledback = false;
 
-   private volatile boolean rolledback;
-
    private AtomicInteger numberOfMessages = new AtomicInteger(0);
+   
+   private List<Pair<PageSubscription, PagePosition>> lateDeliveries;
 
    // Static --------------------------------------------------------
 
@@ -61,7 +69,6 @@
    {
       this();
       this.transactionID = transactionID;
-      countDownCompleted = new CountDownLatch(1);
    }
 
    public PageTransactionInfoImpl()
@@ -85,7 +92,7 @@
       return transactionID;
    }
 
-   public void update(final int update, final StorageManager storageManager, PagingManager pagingManager)
+   public void onUpdate(final int update, final StorageManager storageManager, PagingManager pagingManager)
    {
       int sizeAfterUpdate = numberOfMessages.addAndGet(-update);
       if (sizeAfterUpdate == 0 && storageManager != null)
@@ -98,10 +105,7 @@
          {
             log.warn("Can't delete page transaction id=" + this.recordID);
          }
-      }
-      
-      if (sizeAfterUpdate == 0 && pagingManager != null)
-      {
+
          pagingManager.removeTransaction(this.transactionID);
       }
    }
@@ -110,6 +114,11 @@
    {
       numberOfMessages.incrementAndGet();
    }
+   
+   public void increment(final int size)
+   {
+      numberOfMessages.addAndGet(size);
+   }
 
    public int getNumberOfMessages()
    {
@@ -122,7 +131,6 @@
    {
       transactionID = buffer.readLong();
       numberOfMessages.set(buffer.readInt());
-      countDownCompleted = null;
       committed = true;
    }
 
@@ -137,25 +145,18 @@
       return DataConstants.SIZE_LONG + DataConstants.SIZE_INT;
    }
 
-   public void commit()
+   public synchronized void commit()
    {
-      committed = true;
-      /** 
-       * this is to avoid a race condition where the transaction still being committed while another thread is depaging messages
-       */
-      countDownCompleted.countDown();
-   }
-
-   public boolean waitCompletion(final int timeoutMilliseconds) throws InterruptedException
-   {
-      if (countDownCompleted == null)
+      if (lateDeliveries != null)
       {
-         return true;
+         for (Pair<PageSubscription, PagePosition> pos : lateDeliveries)
+         {
+            pos.a.redeliver(pos.b);
+         }
+         lateDeliveries.clear();
       }
-      else
-      {
-         return countDownCompleted.await(timeoutMilliseconds, TimeUnit.MILLISECONDS);
-      }
+      committed = true;
+      lateDeliveries = null;
    }
 
    public void store(final StorageManager storageManager, PagingManager pagingManager, final Transaction tx) throws Exception
@@ -166,38 +167,35 @@
    /* (non-Javadoc)
     * @see org.hornetq.core.paging.PageTransactionInfo#storeUpdate(org.hornetq.core.persistence.StorageManager, org.hornetq.core.transaction.Transaction, int)
     */
-   public void storeUpdate(final StorageManager storageManager, final PagingManager pagingManager, final Transaction tx, final int depages) throws Exception
+   public void storeUpdate(final StorageManager storageManager, final PagingManager pagingManager, final Transaction tx) throws Exception
    {
-      storageManager.updatePageTransaction(tx.getID(), this, depages);
+      UpdatePageTXOperation pgtxUpdate = (UpdatePageTXOperation)tx.getProperty(TransactionPropertyIndexes.PAGE_TRANSACTION_UPDATE);
       
-      final PageTransactionInfo pgToUpdate = this;
+      if (pgtxUpdate == null)
+      {
+         pgtxUpdate = new UpdatePageTXOperation(storageManager, pagingManager);
+         tx.putProperty(TransactionPropertyIndexes.PAGE_TRANSACTION_UPDATE, pgtxUpdate);
+         tx.addOperation(pgtxUpdate);
+      }
       
-      tx.addOperation(new TransactionOperation()
+      tx.setContainsPersistent();
+      
+      pgtxUpdate.addUpdate(this);
+   }
+   
+   public void storeUpdate(final StorageManager storageManager, final PagingManager pagingManager) throws Exception
+   {
+      storageManager.updatePageTransaction(this, 1);
+      storageManager.afterCompleteOperations(new IOAsyncTask()
       {
-         public void beforeRollback(Transaction tx) throws Exception
+         public void onError(int errorCode, String errorMessage)
          {
          }
          
-         public void beforePrepare(Transaction tx) throws Exception
+         public void done()
          {
+            PageTransactionInfoImpl.this.onUpdate(1, storageManager, pagingManager);
          }
-         
-         public void beforeCommit(Transaction tx) throws Exception
-         {
-         }
-         
-         public void afterRollback(Transaction tx)
-         {
-         }
-         
-         public void afterPrepare(Transaction tx)
-         {
-         }
-         
-         public void afterCommit(Transaction tx)
-         {
-            pgToUpdate.update(depages, storageManager, pagingManager);
-         }
 
          public List<MessageReference> getRelatedMessageReferences()
          {
@@ -205,6 +203,8 @@
          }
       });
    }
+   
+   
 
    public boolean isCommit()
    {
@@ -216,19 +216,18 @@
       return rolledback;
    }
 
-   public void rollback()
+   public synchronized void rollback()
    {
       rolledback = true;
       committed = false;
-      countDownCompleted.countDown();
-   }
 
-   public void markIncomplete()
-   {
-      committed = false;
-      rolledback = false;
-
-      countDownCompleted = new CountDownLatch(1);
+      if (lateDeliveries != null)
+      {
+         for (Pair<PageSubscription, PagePosition> pos : lateDeliveries)
+         {
+            pos.a.positionIgnored(pos.b);
+         }
+      }
    }
 
    public String toString()
@@ -241,6 +240,39 @@
              ")";
    }
 
+   /* (non-Javadoc)
+    * @see org.hornetq.core.paging.PageTransactionInfo#deliverAfterCommit(org.hornetq.core.paging.cursor.PageCursor, org.hornetq.core.paging.cursor.PagePosition)
+    */
+   public synchronized boolean deliverAfterCommit(PageSubscription cursor, PagePosition cursorPos)
+   {
+      if (committed && useRedelivery)
+      {
+         cursor.redeliver(cursorPos);
+         return true;
+      }
+      else
+      if (committed)
+      {
+         return false;
+      }
+      else
+      if (rolledback)
+      {
+         cursor.positionIgnored(cursorPos);
+         return true;
+      }
+      else
+      {
+         useRedelivery = true;
+         if (lateDeliveries == null)
+         {
+            lateDeliveries = new LinkedList<Pair<PageSubscription, PagePosition>>();
+         }
+         lateDeliveries.add(new Pair<PageSubscription, PagePosition>(cursor, cursorPos));
+         return true;
+      }
+   }
+
    // Package protected ---------------------------------------------
 
    // Protected -----------------------------------------------------
@@ -248,4 +280,68 @@
    // Private -------------------------------------------------------
 
    // Inner classes -------------------------------------------------
+   
+   
+   static class UpdatePageTXOperation extends TransactionOperationAbstract
+   {
+      private HashMap<PageTransactionInfo, AtomicInteger> countsToUpdate = new HashMap<PageTransactionInfo, AtomicInteger>();
+      
+      private boolean stored = false;
+      
+      private final StorageManager storageManager;
+      
+      private final PagingManager pagingManager;
+      
+      public UpdatePageTXOperation(final StorageManager storageManager, final PagingManager pagingManager)
+      {
+         this.storageManager = storageManager;
+         this.pagingManager = pagingManager;
+      }
+      
+      public void addUpdate(PageTransactionInfo info)
+      {
+         AtomicInteger counter = countsToUpdate.get(info);
+         
+         if (counter == null)
+         {
+            counter = new AtomicInteger(0);
+            countsToUpdate.put(info, counter);
+         }
+         
+         counter.incrementAndGet();
+      }
+      
+      public void beforePrepare(Transaction tx) throws Exception
+      {
+         storeUpdates(tx);
+      }
+      
+      public void beforeCommit(Transaction tx) throws Exception
+      {
+         storeUpdates(tx);
+      }
+      
+      public void afterCommit(Transaction tx)
+      {
+         for (Map.Entry<PageTransactionInfo, AtomicInteger> entry : countsToUpdate.entrySet())
+         {
+            entry.getKey().onUpdate(entry.getValue().intValue(), storageManager, pagingManager);
+         }
+      }
+      
+      private void storeUpdates(Transaction tx) throws Exception
+      {
+         if (!stored)
+         {
+            stored = true;
+            for (Map.Entry<PageTransactionInfo, AtomicInteger> entry : countsToUpdate.entrySet())
+            {
+               storageManager.updatePageTransaction(tx.getID(), entry.getKey(), entry.getValue().get());
+            }
+         }
+      }
+      
+
+      
+   }
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagedMessageImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagedMessageImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagedMessageImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -49,17 +49,20 @@
    private byte[] largeMessageLazyData;
 
    private ServerMessage message;
+   
+   private long queueIDs[];
 
-   private long transactionID = -1;
+   private long transactionID = 0;
 
-   public PagedMessageImpl(final ServerMessage message, final long transactionID)
+   public PagedMessageImpl(final ServerMessage message, final long[] queueIDs, final long transactionID)
    {
-      this.message = message;
+      this(message, queueIDs);
       this.transactionID = transactionID;
    }
 
-   public PagedMessageImpl(final ServerMessage message)
+   public PagedMessageImpl(final ServerMessage message, final long[] queueIDs)
    {
+      this.queueIDs = queueIDs;
       this.message = message;
    }
 
@@ -67,8 +70,13 @@
    {
    }
 
-   public ServerMessage getMessage(final StorageManager storage)
+   public ServerMessage getMessage()
    {
+      return message;
+   }
+   
+   public void initMessage(StorageManager storage)
+   {
       if (largeMessageLazyData != null)
       {
          message = storage.createLargeMessage();
@@ -76,13 +84,17 @@
          message.decodeHeadersAndProperties(buffer);
          largeMessageLazyData = null;
       }
-      return message;
    }
 
    public long getTransactionID()
    {
       return transactionID;
    }
+   
+   public long[] getQueueIDs()
+   {
+      return queueIDs;
+   }
 
    // EncodingSupport implementation --------------------------------
 
@@ -108,6 +120,15 @@
 
          message.decode(buffer);
       }
+      
+      int queueIDsSize = buffer.readInt();
+      
+      queueIDs = new long[queueIDsSize];
+      
+      for (int i = 0 ; i < queueIDsSize; i++)
+      {
+         queueIDs[i] = buffer.readLong();
+      }
    }
 
    public void encode(final HornetQBuffer buffer)
@@ -119,11 +140,19 @@
       buffer.writeInt(message.getEncodeSize());
 
       message.encode(buffer);
+      
+      buffer.writeInt(queueIDs.length);
+      
+      for (int i = 0 ; i < queueIDs.length; i++)
+      {
+         buffer.writeLong(queueIDs[i]);
+      }
    }
 
    public int getEncodeSize()
    {
-      return DataConstants.SIZE_LONG + DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + message.getEncodeSize();
+      return DataConstants.SIZE_LONG + DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + message.getEncodeSize() + 
+             DataConstants.SIZE_INT + queueIDs.length * DataConstants.SIZE_LONG;
    }
 
    // Package protected ---------------------------------------------

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagingManagerImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagingManagerImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagingManagerImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -228,14 +228,23 @@
          }
       }
    }
+   
+   public void processReload() throws Exception
+   {
+      for (PagingStore store: stores.values())
+      {
+         store.processReload();
+      }
+   }
 
+
    // Package protected ---------------------------------------------
 
    // Protected -----------------------------------------------------
 
    // Private -------------------------------------------------------
 
-   protected PagingStore newStore(final SimpleString address) throws Exception
+   protected PagingStore newStore(final SimpleString address) 
    {
       return pagingStoreFactory.newStore(address,
                                          addressSettingsRepository.getMatch(address.toString()));

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagingStoreFactoryNIO.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagingStoreFactoryNIO.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagingStoreFactoryNIO.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -87,7 +87,7 @@
    {
    }
 
-   public synchronized PagingStore newStore(final SimpleString address, final AddressSettings settings) throws Exception
+   public synchronized PagingStore newStore(final SimpleString address, final AddressSettings settings)
    {
 
       return new PagingStoreImpl(address,
@@ -98,7 +98,7 @@
                                  this,
                                  address,
                                  settings,
-                                 executorFactory.getExecutor(),
+                                 executorFactory,
                                  syncNonTransactional);
    }
 
@@ -202,7 +202,7 @@
                                                     this,
                                                     address,
                                                     settings,
-                                                    executorFactory.getExecutor(),
+                                                    executorFactory,
                                                     syncNonTransactional);
 
             storesReturn.add(store);

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -14,20 +14,15 @@
 package org.hornetq.core.paging.impl;
 
 import java.text.DecimalFormat;
-import java.util.Arrays;
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.Queue;
 import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.hornetq.api.core.SimpleString;
@@ -40,17 +35,25 @@
 import org.hornetq.core.paging.PagingManager;
 import org.hornetq.core.paging.PagingStore;
 import org.hornetq.core.paging.PagingStoreFactory;
+import org.hornetq.core.paging.cursor.LivePageCache;
+import org.hornetq.core.paging.cursor.PageCursorProvider;
+import org.hornetq.core.paging.cursor.impl.LivePageCacheImpl;
+import org.hornetq.core.paging.cursor.impl.PageCursorProviderImpl;
 import org.hornetq.core.persistence.StorageManager;
 import org.hornetq.core.postoffice.DuplicateIDCache;
 import org.hornetq.core.postoffice.PostOffice;
-import org.hornetq.core.server.LargeServerMessage;
+import org.hornetq.core.server.MessageReference;
+import org.hornetq.core.server.RouteContextList;
+import org.hornetq.core.server.RoutingContext;
 import org.hornetq.core.server.ServerMessage;
 import org.hornetq.core.settings.impl.AddressFullMessagePolicy;
 import org.hornetq.core.settings.impl.AddressSettings;
 import org.hornetq.core.transaction.Transaction;
-import org.hornetq.core.transaction.TransactionPropertyIndexes;
 import org.hornetq.core.transaction.Transaction.State;
-import org.hornetq.core.transaction.impl.TransactionImpl;
+import org.hornetq.core.transaction.TransactionOperation;
+import org.hornetq.core.transaction.TransactionPropertyIndexes;
+import org.hornetq.utils.ExecutorFactory;
+import org.hornetq.utils.Future;
 
 /**
  * 
@@ -109,17 +112,16 @@
    private volatile int currentPageId;
 
    private volatile Page currentPage;
+   
+   private volatile boolean paging = false;
 
-   private final ReentrantLock writeLock = new ReentrantLock();
-
    /** duplicate cache used at this address */
    private final DuplicateIDCache duplicateCache;
 
-   /** 
-    * We need to perform checks on currentPage with minimal locking
-    * */
-   private final ReadWriteLock currentPageLock = new ReentrantReadWriteLock();
+   private final PageCursorProvider cursorProvider;
 
+   private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
    private volatile boolean running = false;
 
    protected final boolean syncNonTransactional;
@@ -146,7 +148,7 @@
                           final PagingStoreFactory storeFactory,
                           final SimpleString storeName,
                           final AddressSettings addressSettings,
-                          final Executor executor,
+                          final ExecutorFactory executorFactory,
                           final boolean syncNonTransactional)
    {
       if (pagingManager == null)
@@ -178,7 +180,7 @@
                                          pageSize);
       }
 
-      this.executor = executor;
+      this.executor = executorFactory.getExecutor();
 
       this.pagingManager = pagingManager;
 
@@ -188,6 +190,8 @@
 
       this.syncNonTransactional = syncNonTransactional;
 
+      this.cursorProvider = new PageCursorProviderImpl(this, this.storageManager, executorFactory);
+
       // Post office could be null on the backup node
       if (postOffice == null)
       {
@@ -202,8 +206,38 @@
 
    // Public --------------------------------------------------------
 
+   public String toString()
+   {
+      return "PagingStoreImpl(" + this.address + ")";
+   }
+
    // PagingStore implementation ------------------------------------
 
+   public void lock()
+   {
+      lock.writeLock().lock();
+   }
+
+   public void unlock()
+   {
+      lock.writeLock().unlock();
+   }
+
+   public PageCursorProvider getCursorProvier()
+   {
+      return cursorProvider;
+   }
+
+   public long getFirstPage()
+   {
+      return firstPageId;
+   }
+
+   public long getTopPage()
+   {
+      return currentPageId;
+   }
+
    public SimpleString getAddress()
    {
       return address;
@@ -231,7 +265,7 @@
 
    public boolean isPaging()
    {
-      currentPageLock.readLock().lock();
+      lock.readLock().lock();
 
       try
       {
@@ -245,12 +279,12 @@
          }
          else
          {
-            return currentPage != null;
+            return paging;
          }
       }
       finally
       {
-         currentPageLock.readLock().unlock();
+         lock.readLock().unlock();
       }
    }
 
@@ -259,27 +293,31 @@
       return numberOfPages;
    }
 
+   public int getCurrentWritingPage()
+   {
+      return currentPageId;
+   }
+
    public SimpleString getStoreName()
    {
       return storeName;
    }
-
-   public boolean page(final List<ServerMessage> message, final long transactionID) throws Exception
+   
+   public boolean page(final ServerMessage message, final RoutingContext ctx) throws Exception
    {
-      // The sync on transactions is done on commit only
-      return page(message, transactionID, false);
+      return page(message, ctx, ctx.getContextListing(storeName));
    }
 
-   public boolean page(final ServerMessage message) throws Exception
+   public boolean page(final ServerMessage message, final RoutingContext ctx, RouteContextList listCtx) throws Exception
    {
-      // If non Durable, there is no need to sync as there is no requirement for persistence for those messages in case
-      // of crash
-      return page(Arrays.asList(message), -1, syncNonTransactional && message.isDurable());
+      // The sync on transactions is done on commit only
+      // TODO: sync on paging
+      return page(message, ctx, listCtx, false);
    }
 
    public void sync() throws Exception
    {
-      currentPageLock.readLock().lock();
+      lock.readLock().lock();
 
       try
       {
@@ -290,12 +328,18 @@
       }
       finally
       {
-         currentPageLock.readLock().unlock();
+         lock.readLock().unlock();
       }
    }
 
    public boolean startDepaging()
    {
+
+      // Disabled for now
+
+      return false;
+
+      /*
       if (!running)
       {
          return false;
@@ -332,12 +376,22 @@
       finally
       {
          currentPageLock.readLock().unlock();
-      }
+      } */
    }
 
+   public void processReload() throws Exception
+   {
+      cursorProvider.processReload();
+   }
+
+   public PagingManager getPagingManager()
+   {
+      return pagingManager;
+   }
+
    // HornetQComponent implementation
 
-   public synchronized boolean isStarted()
+   public boolean isStarted()
    {
       return running;
    }
@@ -346,22 +400,12 @@
    {
       if (running)
       {
-         running = false;
 
-         final CountDownLatch latch = new CountDownLatch(1);
+         cursorProvider.stop();
 
-         executor.execute(new Runnable()
-         {
-            public void run()
-            {
-               latch.countDown();
-            }
-         });
+         running = false;
 
-         if (!latch.await(60, TimeUnit.SECONDS))
-         {
-            PagingStoreImpl.log.warn("Timed out on waiting PagingStore " + address + " to shutdown");
-         }
+         flushExecutors();
 
          if (currentPage != null)
          {
@@ -370,10 +414,24 @@
          }
       }
    }
+   
+   public void flushExecutors()
+   {
+      cursorProvider.flushExecutors();
+      
+      Future future = new Future();
 
+      executor.execute(future);
+
+      if (!future.await(60000))
+      {
+         PagingStoreImpl.log.warn("Timed out on waiting PagingStore " + address + " to shutdown");
+      }
+   }
+
    public void start() throws Exception
    {
-      writeLock.lock();
+      lock.writeLock().lock();
 
       try
       {
@@ -389,57 +447,78 @@
          }
          else
          {
-            currentPageLock.writeLock().lock();
+            running = true;
+            firstPageId = Integer.MAX_VALUE;
 
-            try
+            // There are no files yet on this Storage. We will just return it empty
+            if (fileFactory != null)
             {
-               running = true;
-               firstPageId = Integer.MAX_VALUE;
 
-               // There are no files yet on this Storage. We will just return it empty
-               if (fileFactory != null)
-               {
+               currentPageId = 0;
+               currentPage = null;
 
-                  currentPageId = 0;
-                  currentPage = null;
+               List<String> files = fileFactory.listFiles("page");
 
-                  List<String> files = fileFactory.listFiles("page");
+               numberOfPages = files.size();
 
-                  numberOfPages = files.size();
+               for (String fileName : files)
+               {
+                  final int fileId = PagingStoreImpl.getPageIdFromFileName(fileName);
 
-                  for (String fileName : files)
+                  if (fileId > currentPageId)
                   {
-                     final int fileId = PagingStoreImpl.getPageIdFromFileName(fileName);
+                     currentPageId = fileId;
+                  }
 
-                     if (fileId > currentPageId)
-                     {
-                        currentPageId = fileId;
-                     }
-
-                     if (fileId < firstPageId)
-                     {
-                        firstPageId = fileId;
-                     }
+                  if (fileId < firstPageId)
+                  {
+                     firstPageId = fileId;
                   }
+               }
 
-                  if (numberOfPages != 0)
+               if (currentPageId != 0)
+               {
+                  currentPage = createPage(currentPageId);
+                  currentPage.open();
+
+                  List<PagedMessage> messages = currentPage.read();
+
+                  LivePageCache pageCache = new LivePageCacheImpl(currentPage);
+
+                  for (PagedMessage msg : messages)
                   {
-                     startPaging();
+                     msg.initMessage(storageManager);
+                     pageCache.addLiveMessage(msg);
                   }
+
+                  currentPage.setLiveCache(pageCache);
+
+                  currentPageSize.set(currentPage.getSize());
+
+                  cursorProvider.addPageCache(pageCache);
                }
+               
+               // We will not mark it for paging if there's only a single empty file
+               if (currentPage != null && !(numberOfPages == 1 && currentPage.getSize() == 0))
+               {
+                  startPaging();
+               }
             }
-            finally
-            {
-               currentPageLock.writeLock().unlock();
-            }
          }
 
       }
       finally
       {
-         writeLock.unlock();
+         lock.writeLock().unlock();
       }
    }
+   
+   public void stopPaging()
+   {
+      lock.writeLock().lock();
+      paging = false;
+      lock.writeLock().unlock();
+   }
 
    public boolean startPaging()
    {
@@ -448,28 +527,30 @@
          return false;
       }
 
-      // First check without any global locks.
-      // (Faster)
-      currentPageLock.readLock().lock();
+      lock.readLock().lock();
       try
       {
-         // Already paging, nothing to be done
-         if (currentPage != null)
+         if (paging)
          {
             return false;
          }
       }
       finally
       {
-         currentPageLock.readLock().unlock();
+         lock.readLock().unlock();
       }
 
       // if the first check failed, we do it again under a global currentPageLock
       // (writeLock) this time
-      writeLock.lock();
+      lock.writeLock().lock();
 
       try
       {
+         if (paging)
+         {
+            return false;
+         }
+         
          if (currentPage == null)
          {
             try
@@ -483,17 +564,15 @@
                PagingStoreImpl.log.warn("IO Error, impossible to start paging", e);
                return false;
             }
-
-            return true;
          }
-         else
-         {
-            return false;
-         }
+
+         paging = true;
+         
+         return true;
       }
       finally
       {
-         writeLock.unlock();
+         lock.writeLock().unlock();
       }
    }
 
@@ -502,9 +581,9 @@
       return currentPage;
    }
 
-   public Page createPage(final int page) throws Exception
+   public Page createPage(final int pageNumber) throws Exception
    {
-      String fileName = createFileName(page);
+      String fileName = createFileName(pageNumber);
 
       if (fileFactory == null)
       {
@@ -513,17 +592,18 @@
 
       SequentialFile file = fileFactory.createSequentialFile(fileName, 1000);
 
+      Page page = new PageImpl(storeName, storageManager, fileFactory, file, pageNumber);
+
+      // To create the file
       file.open();
 
       file.position(0);
 
       file.close();
 
-      return new PageImpl(storeName, storageManager, fileFactory, file, page);
+      return page;
    }
 
-   // TestSupportPageStore ------------------------------------------
-
    public void forceAnotherPage() throws Exception
    {
       openNewPage();
@@ -539,9 +619,7 @@
     * */
    public Page depage() throws Exception
    {
-      writeLock.lock();
-
-      currentPageLock.writeLock().lock(); // Make sure no checks are done on currentPage while we are depaging
+      lock.writeLock().lock(); // Make sure no checks are done on currentPage while we are depaging
       try
       {
          if (!running)
@@ -578,6 +656,7 @@
                // The current page is empty... which means we reached the end of the pages
                if (returnPage.getNumberOfMessages() == 0)
                {
+                  stopPaging();
                   returnPage.open();
                   returnPage.delete();
 
@@ -603,8 +682,7 @@
       }
       finally
       {
-         currentPageLock.writeLock().unlock();
-         writeLock.unlock();
+         lock.writeLock().unlock();
       }
 
    }
@@ -620,59 +698,6 @@
     * @return
     * @throws Exception
     */
-   protected boolean readPage() throws Exception
-   {
-      Page page = depage();
-
-      // It's important that only depage should happen while locked
-      // or we would be holding a lock for a long time
-      // The reading (IO part) should happen outside of any locks
-
-      if (page == null)
-      {
-         return false;
-      }
-
-      page.open();
-
-      List<PagedMessage> messages = null;
-
-      try
-      {
-         messages = page.read();
-      }
-      finally
-      {
-         try
-         {
-            page.close();
-         }
-         catch (Throwable ignored)
-         {
-         }
-      }
-
-      if (onDepage(page.getPageId(), storeName, messages))
-      {
-         if (page.delete())
-         {
-            // DuplicateCache could be null during replication
-            // however the deletes on the journal will happen through replicated journal
-            if (duplicateCache != null)
-            {
-               duplicateCache.deleteFromCache(generateDuplicateID(page.getPageId()));
-            }
-         }
-
-         return true;
-      }
-      else
-      {
-         return false;
-      }
-
-   }
-
    private Queue<OurRunnable> onMemoryFreedRunnables = new ConcurrentLinkedQueue<OurRunnable>();
 
    private class MemoryFreedRunnablesExecutor implements Runnable
@@ -802,7 +827,7 @@
 
    }
 
-   protected boolean page(final List<ServerMessage> messages, final long transactionID, final boolean sync) throws Exception
+   protected boolean page(ServerMessage message, final RoutingContext ctx, RouteContextList listCtx, final boolean sync) throws Exception
    {
       if (!running)
       {
@@ -836,252 +861,182 @@
       }
 
       // We need to ensure a read lock, as depage could change the paging state
-      currentPageLock.readLock().lock();
+      lock.readLock().lock();
 
       try
       {
          // First check done concurrently, to avoid synchronization and increase throughput
-         if (currentPage == null)
+         if (!paging)
          {
             return false;
          }
       }
       finally
       {
-         currentPageLock.readLock().unlock();
+         lock.readLock().unlock();
       }
 
-      writeLock.lock();
+      lock.writeLock().lock();
 
       try
       {
-         if (currentPage == null)
+         if (!paging)
          {
             return false;
          }
 
-         for (ServerMessage message : messages)
+         PagedMessage pagedMessage;
+
+         if (!message.isDurable())
          {
-            PagedMessage pagedMessage;
+            // The address should never be transient when paging (even for non-persistent messages when paging)
+            // This will force everything to be persisted
+            message.bodyChanged();
+         }
+         
+         Transaction tx = ctx.getTransaction();
 
-            if (!message.isDurable())
-            {
-               // The address should never be transient when paging (even for non-persistent messages when paging)
-               // This will force everything to be persisted
-               message.bodyChanged();
-            }
+         pagedMessage = new PagedMessageImpl(message, getQueueIDs(listCtx), getTransactionID(tx, listCtx));
 
-            if (transactionID != -1)
-            {
-               pagedMessage = new PagedMessageImpl(message, transactionID);
-            }
-            else
-            {
-               pagedMessage = new PagedMessageImpl(message);
-            }
+         int bytesToWrite = pagedMessage.getEncodeSize() + PageImpl.SIZE_RECORD;
 
-            int bytesToWrite = pagedMessage.getEncodeSize() + PageImpl.SIZE_RECORD;
-
-            if (currentPageSize.addAndGet(bytesToWrite) > pageSize && currentPage.getNumberOfMessages() > 0)
-            {
-               // Make sure nothing is currently validating or using currentPage
-               currentPageLock.writeLock().lock();
-               try
-               {
-                  openNewPage();
-
-                  // openNewPage will set currentPageSize to zero, we need to set it again
-                  currentPageSize.addAndGet(bytesToWrite);
-               }
-               finally
-               {
-                  currentPageLock.writeLock().unlock();
-               }
-            }
-
-            currentPageLock.readLock().lock();
-
-            try
-            {
-               currentPage.write(pagedMessage);
- 
-               if (sync)
-               {
-                  currentPage.sync();
-               }
-            }
-            finally
-            {
-               currentPageLock.readLock().unlock();
-            }
+         if (currentPageSize.addAndGet(bytesToWrite) > pageSize && currentPage.getNumberOfMessages() > 0)
+         {
+            // Make sure nothing is currently validating or using currentPage
+            openNewPage();
          }
 
+         currentPage.write(pagedMessage);
+
          return true;
       }
       finally
       {
-         writeLock.unlock();
+         lock.writeLock().unlock();
       }
 
    }
 
-   /**
-    * This method will remove files from the page system and and route them, doing it transactionally
-    *     
-    * If persistent messages are also used, it will update eventual PageTransactions
-    */
-
-   private boolean onDepage(final int pageId, final SimpleString address, final List<PagedMessage> pagedMessages) throws Exception
+   private long[] getQueueIDs(RouteContextList ctx)
    {
-      if (PagingStoreImpl.isTrace)
+      List<org.hornetq.core.server.Queue> durableQueues = ctx.getDurableQueues();
+      List<org.hornetq.core.server.Queue> nonDurableQueues = ctx.getNonDurableQueues();
+      long ids[] = new long [durableQueues.size() + nonDurableQueues.size()];
+      int i = 0;
+      
+      for (org.hornetq.core.server.Queue q : durableQueues)
       {
-         PagingStoreImpl.trace("Depaging....");
+         ids[i++] = q.getID();
       }
-
-      if (pagedMessages.size() == 0)
+      
+      for (org.hornetq.core.server.Queue q : nonDurableQueues)
       {
-         // nothing to be done on this case.
-         return true;
+         ids[i++] = q.getID();
       }
-
-      // Depage has to be done atomically, in case of failure it should be
-      // back to where it was
-
-      byte[] duplicateIdForPage = generateDuplicateID(pageId);
-
-      Transaction depageTransaction = new TransactionImpl(storageManager);
-
-      // DuplicateCache could be null during replication
-      if (duplicateCache != null)
+      return ids;
+   }
+   
+   private long getTransactionID(final Transaction tx, final RouteContextList listCtx) throws Exception
+   {
+      if (tx == null)
       {
-         if (duplicateCache.contains(duplicateIdForPage))
+         return 0l;
+      }
+      else
+      {
+         PageTransactionInfo pgTX = (PageTransactionInfo) tx.getProperty(TransactionPropertyIndexes.PAGE_TRANSACTION);
+         if (pgTX == null)
          {
-            log.warn("Page " + pageId +
-                     " had been processed already but the file wasn't removed as a crash happened. Ignoring this page");
-            return true;
+            pgTX = new PageTransactionInfoImpl(tx.getID());
+            System.out.println("Creating pageTransaction " + pgTX.getTransactionID());
+            pagingManager.addTransaction(pgTX);
+            tx.putProperty(TransactionPropertyIndexes.PAGE_TRANSACTION, pgTX);
+            tx.addOperation(new FinishPageMessageOperation(pgTX));
          }
-
-         duplicateCache.addToCache(duplicateIdForPage, depageTransaction);
+         
+         pgTX.increment(listCtx.getNumberOfQueues());
+         
+         return tx.getID();
       }
+   }
 
-      depageTransaction.putProperty(TransactionPropertyIndexes.IS_DEPAGE, Boolean.valueOf(true));
+   
+   private class FinishPageMessageOperation implements TransactionOperation
+   {
+      private final PageTransactionInfo pageTransaction;
+      
+      private boolean stored = false;
 
-      HashMap<PageTransactionInfo, AtomicInteger> pageTransactionsToUpdate = new HashMap<PageTransactionInfo, AtomicInteger>();
-
-      for (PagedMessage pagedMessage : pagedMessages)
+      public FinishPageMessageOperation(final PageTransactionInfo pageTransaction)
       {
-         ServerMessage message = pagedMessage.getMessage(storageManager);
+         this.pageTransaction = pageTransaction;
+      }
+      
+      public void afterCommit(final Transaction tx)
+      {
+         // If part of the transaction goes to the queue, and part goes to paging, we can't let depage start for the
+         // transaction until all the messages were added to the queue
+         // or else we could deliver the messages out of order
 
-         if (message.isLargeMessage())
+         if (pageTransaction != null)
          {
-            LargeServerMessage largeMsg = (LargeServerMessage)message;
-            if (!largeMsg.isFileExists())
-            {
-               PagingStoreImpl.log.warn("File for large message " + largeMsg.getMessageID() +
-                                        " doesn't exist, so ignoring depage for this large message");
-               continue;
-            }
+            pageTransaction.commit();
          }
+      }
 
-         final long transactionIdDuringPaging = pagedMessage.getTransactionID();
+      public void afterPrepare(final Transaction tx)
+      {
+      }
 
-         PageTransactionInfo pageUserTransaction = null;
-         AtomicInteger countPageTX = null;
-
-         if (transactionIdDuringPaging >= 0)
+      public void afterRollback(final Transaction tx)
+      {
+         if (tx.getState() == State.PREPARED && pageTransaction != null)
          {
-            pageUserTransaction = pagingManager.getTransaction(transactionIdDuringPaging);
-
-            if (pageUserTransaction == null)
-            {
-               // This is not supposed to happen
-               PagingStoreImpl.log.warn("Transaction " + pagedMessage.getTransactionID() +
-                                        " used during paging not found");
-               continue;
-            }
-            else
-            {
-               countPageTX = pageTransactionsToUpdate.get(pageUserTransaction);
-               if (countPageTX == null)
-               {
-                  countPageTX = new AtomicInteger();
-                  pageTransactionsToUpdate.put(pageUserTransaction, countPageTX);
-               }
-
-               // This is to avoid a race condition where messages are depaged
-               // before the commit arrived
-
-               while (running && !pageUserTransaction.waitCompletion(500))
-               {
-                  // This is just to give us a chance to interrupt the process..
-                  // if we start a shutdown in the middle of transactions, the commit/rollback may never come, delaying
-                  // the shutdown of the server
-                  if (PagingStoreImpl.isTrace)
-                  {
-                     PagingStoreImpl.trace("Waiting pageTransaction to complete");
-                  }
-               }
-
-               if (!running)
-               {
-                  break;
-               }
-
-               if (!pageUserTransaction.isCommit())
-               {
-                  if (PagingStoreImpl.isTrace)
-                  {
-                     PagingStoreImpl.trace("Rollback was called after prepare, ignoring message " + message);
-                  }
-                  continue;
-               }
-            }
-
+            pageTransaction.rollback();
          }
+      }
 
-         postOffice.route(message, depageTransaction, false);
+      public void beforeCommit(final Transaction tx) throws Exception
+      {
+         storePageTX(tx);
+      }
 
-         // This means the page is duplicated. So we need to ignore this
-         if (depageTransaction.getState() == State.ROLLBACK_ONLY)
+      public void beforePrepare(final Transaction tx) throws Exception
+      {
+         storePageTX(tx);
+      }
+      
+      private void storePageTX(final Transaction tx) throws Exception
+      {
+         if (!stored)
          {
-            break;
+            tx.setContainsPersistent();
+            pageTransaction.store(storageManager, pagingManager, tx);
+            stored = true;
          }
-
-         // Update information about transactions
-         // This needs to be done after routing because of duplication detection
-         if (pageUserTransaction != null && message.isDurable())
-         {
-            countPageTX.incrementAndGet();
-         }
       }
 
-      if (!running)
+      public void beforeRollback(final Transaction tx) throws Exception
       {
-         depageTransaction.rollback();
-         return false;
       }
 
-      for (Map.Entry<PageTransactionInfo, AtomicInteger> entry : pageTransactionsToUpdate.entrySet())
+      /* (non-Javadoc)
+       * @see org.hornetq.core.transaction.TransactionOperation#getRelatedMessageReferences()
+       */
+      public List<MessageReference> getRelatedMessageReferences()
       {
-         // This will set the journal transaction to commit;
-         depageTransaction.setContainsPersistent();
-
-         entry.getKey().storeUpdate(storageManager, this.pagingManager, depageTransaction, entry.getValue().intValue());
+         return Collections.emptyList();
       }
 
-      depageTransaction.commit();
-
-      storageManager.waitOnOperations();
-
-      if (PagingStoreImpl.isTrace)
-      {
-         PagingStoreImpl.trace("Depage committed, running = " + running);
-      }
-
-      return true;
    }
 
    /**
+    * This method will remove files from the page system and and route them, doing it transactionally
+    *     
+    * If persistent messages are also used, it will update eventual PageTransactions
+    */
+
+    /**
     * @param pageId
     * @return
     */
@@ -1091,77 +1046,45 @@
       return duplicateIdForPage;
    }
 
-   /**
-    * @return
-    */
-   private boolean isAddressFull(final long nextPageSize)
-   {
-      return maxSize > 0 && getAddressSize() + nextPageSize > maxSize;
-   }
+   
 
-   /**
-    * startDepaging and clearDepage needs to be atomic.
-    * We can't use writeLock to this operation as writeLock would still be used by another thread, and still being a valid usage
-    * @return true if the depage status was cleared
-    */
-   private synchronized boolean clearDepage()
-   {
-      final boolean addressFull = isAddressFull(getPageSizeBytes());
-
-      if (PagingStoreImpl.isTrace)
-      {
-         PagingStoreImpl.trace("Clear Depage on Address = " + getStoreName() +
-                               " addressSize = " +
-                               getAddressSize() +
-                               " addressMax " +
-                               maxSize +
-                               " isPaging = " +
-                               isPaging() +
-                               " addressFull = " +
-                               addressFull);
-      }
-
-      // It should stop the executor when the address is full or when there is nothing else to be depaged
-      if (addressFull || !isPaging())
-      {
-         depaging.set(false);
-         return true;
-      }
-      else
-      {
-         return false;
-      }
-   }
-
    private void openNewPage() throws Exception
    {
-      currentPageLock.writeLock().lock();
+      lock.writeLock().lock();
 
       try
       {
          numberOfPages++;
 
-         currentPageId++;
+         int tmpCurrentPageId = currentPageId + 1;
 
-         if (currentPageId < firstPageId)
-         {
-            firstPageId = currentPageId;
-         }
-
          if (currentPage != null)
          {
             currentPage.close();
          }
 
-         currentPage = createPage(currentPageId);
+         currentPage = createPage(tmpCurrentPageId);
 
+         LivePageCache pageCache = new LivePageCacheImpl(currentPage);
+
+         currentPage.setLiveCache(pageCache);
+
+         cursorProvider.addPageCache(pageCache);
+
          currentPageSize.set(0);
 
          currentPage.open();
+
+         currentPageId = tmpCurrentPageId;
+
+         if (currentPageId < firstPageId)
+         {
+            firstPageId = currentPageId;
+         }
       }
       finally
       {
-         currentPageLock.writeLock().unlock();
+         lock.writeLock().unlock();
       }
    }
 
@@ -1190,39 +1113,39 @@
 
    // Inner classes -------------------------------------------------
 
-   private class DepageRunnable implements Runnable
-   {
-      private final Executor followingExecutor;
-
-      public DepageRunnable(final Executor followingExecutor)
+   /*   private class DepageRunnable implements Runnable
       {
-         this.followingExecutor = followingExecutor;
-      }
+         private final Executor followingExecutor;
 
-      public void run()
-      {
-         try
+         public DepageRunnable(final Executor followingExecutor)
          {
-            if (running)
+            this.followingExecutor = followingExecutor;
+         }
+
+         public void run()
+         {
+            try
             {
-               if (!isAddressFull(getPageSizeBytes()))
+               if (running)
                {
-                  readPage();
-               }
+                  if (!isAddressFull(getPageSizeBytes()))
+                  {
+                     readPage();
+                  }
 
-               // Note: clearDepage is an atomic operation, it needs to be done even if readPage was not executed
-               // however clearDepage shouldn't be executed if the page-store is being stopped, as stop will be holding
-               // the lock and this would dead lock
-               if (running && !clearDepage())
-               {
-                  followingExecutor.execute(this);
+                  // Note: clearDepage is an atomic operation, it needs to be done even if readPage was not executed
+                  // however clearDepage shouldn't be executed if the page-store is being stopped, as stop will be holding
+                  // the lock and this would dead lock
+                  if (running && !clearDepage())
+                  {
+                     followingExecutor.execute(this);
+                  }
                }
             }
+            catch (Throwable e)
+            {
+               PagingStoreImpl.log.error(e, e);
+            }
          }
-         catch (Throwable e)
-         {
-            PagingStoreImpl.log.error(e, e);
-         }
-      }
-   }
+      } */
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/TestSupportPageStore.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/TestSupportPageStore.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/paging/impl/TestSupportPageStore.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -13,7 +13,6 @@
 
 package org.hornetq.core.paging.impl;
 
-import org.hornetq.core.paging.Page;
 import org.hornetq.core.paging.PagingStore;
 
 /**
@@ -23,21 +22,4 @@
  */
 public interface TestSupportPageStore extends PagingStore
 {
-   /** 
-    * Remove the first page from the Writing Queue.
-    * The file will still exist until Page.delete is called, 
-    * So, case the system is reloaded the same Page will be loaded back if delete is not called.
-    *
-    * @throws Exception
-    * 
-    * Note: This should still be part of the interface, even though HornetQ only uses through the 
-    */
-   Page depage() throws Exception;
-
-   void forceAnotherPage() throws Exception;
-
-   /** @return true if paging was started, or false if paging was already started before this call */
-   boolean startPaging() throws Exception;
-
-   Page getCurrentPage();
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/StorageManager.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/StorageManager.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/StorageManager.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -13,7 +13,6 @@
 
 package org.hornetq.core.persistence;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Executor;
@@ -27,6 +26,7 @@
 import org.hornetq.core.paging.PageTransactionInfo;
 import org.hornetq.core.paging.PagedMessage;
 import org.hornetq.core.paging.PagingManager;
+import org.hornetq.core.paging.cursor.PagePosition;
 import org.hornetq.core.persistence.config.PersistedAddressSetting;
 import org.hornetq.core.persistence.config.PersistedRoles;
 import org.hornetq.core.postoffice.Binding;
@@ -98,6 +98,8 @@
    void deleteMessage(long messageID) throws Exception;
 
    void storeAcknowledge(long queueID, long messageID) throws Exception;
+   
+   void storeCursorAcknowledge(long queueID, PagePosition position) throws Exception;
 
    void updateDeliveryCount(MessageReference ref) throws Exception;
 
@@ -113,6 +115,10 @@
 
    void storeAcknowledgeTransactional(long txID, long queueID, long messageID) throws Exception;
 
+   void storeCursorAcknowledgeTransactional(long txID, long queueID, PagePosition position) throws Exception;
+   
+   void deleteCursorAcknowledgeTransactional(long txID, long ackID) throws Exception;
+
    void updateScheduledDeliveryTimeTransactional(long txID, MessageReference ref) throws Exception;
 
    void deleteMessageTransactional(long txID, long queueID, long messageID) throws Exception;
@@ -136,6 +142,8 @@
    void storePageTransaction(long txID, PageTransactionInfo pageTransaction) throws Exception;
    
    void updatePageTransaction(long txID, PageTransactionInfo pageTransaction,  int depage) throws Exception;
+   
+   void updatePageTransaction(PageTransactionInfo pageTransaction,  int depage) throws Exception;
 
    void deletePageTransactional(long recordID) throws Exception;
 
@@ -147,6 +155,7 @@
                                              final PagingManager pagingManager,
                                              final ResourceManager resourceManager,
                                              final Map<Long, Queue> queues,
+                                             Map<Long, QueueBindingInfo> queueInfos,
                                              final Map<SimpleString, List<Pair<byte[], Long>>> duplicateIDMap) throws Exception;
 
    long storeHeuristicCompletion(Xid xid, boolean isCommit) throws Exception;

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/impl/journal/JournalStorageManager.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/impl/journal/JournalStorageManager.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/impl/journal/JournalStorageManager.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -50,6 +50,10 @@
 import org.hornetq.core.paging.PageTransactionInfo;
 import org.hornetq.core.paging.PagedMessage;
 import org.hornetq.core.paging.PagingManager;
+import org.hornetq.core.paging.PagingStore;
+import org.hornetq.core.paging.cursor.PageSubscription;
+import org.hornetq.core.paging.cursor.PagePosition;
+import org.hornetq.core.paging.cursor.impl.PagePositionImpl;
 import org.hornetq.core.paging.impl.PageTransactionInfoImpl;
 import org.hornetq.core.persistence.GroupingInfo;
 import org.hornetq.core.persistence.OperationContext;
@@ -134,6 +138,8 @@
 
    public static final byte HEURISTIC_COMPLETION = 38;
 
+   public static final byte ACKNOWLEDGE_CURSOR = 39;
+
    private UUID persistentID;
 
    private final BatchingIDGenerator idGenerator;
@@ -508,7 +514,16 @@
                                         syncNonTransactional,
                                         getContext(syncNonTransactional));
    }
+   
+   public void storeCursorAcknowledge(long queueID, PagePosition position) throws Exception
+   {
+     long ackID = idGenerator.generateID();
+     position.setRecordID(ackID);
+     messageJournal.appendAddRecord(ackID, ACKNOWLEDGE_CURSOR, new CursorAckRecordEncoding(queueID, position), syncNonTransactional, getContext(syncNonTransactional));
+   }
 
+
+
    public void deleteMessage(final long messageID) throws Exception
    {
       // Messages are deleted on postACK, one after another.
@@ -591,6 +606,16 @@
                                                                               depages));
    }
 
+   public void updatePageTransaction(final PageTransactionInfo pageTransaction, final int depages) throws Exception
+   {
+      messageJournal.appendUpdateRecord(pageTransaction.getRecordID(),
+                                        JournalStorageManager.PAGE_TRANSACTION,
+                                        new PageUpdateTXEncoding(pageTransaction.getTransactionID(),
+                                                                 depages),
+                                        syncNonTransactional,
+                                        getContext(syncNonTransactional));
+   }
+
    public void storeReferenceTransactional(final long txID, final long queueID, final long messageID) throws Exception
    {
       messageJournal.appendUpdateRecordTransactional(txID,
@@ -607,6 +632,26 @@
                                                      new RefEncoding(queueID));
    }
 
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#storeCursorAcknowledgeTransactional(long, long, org.hornetq.core.paging.cursor.PagePosition)
+    */
+   public void storeCursorAcknowledgeTransactional(long txID, long queueID, PagePosition position) throws Exception
+   {
+      long ackID = idGenerator.generateID();
+      position.setRecordID(ackID);
+      messageJournal.appendAddRecordTransactional(txID, ackID, ACKNOWLEDGE_CURSOR, new CursorAckRecordEncoding(queueID, position));
+   }
+   
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#deleteCursorAcknowledgeTransactional(long, long)
+    */
+   public void deleteCursorAcknowledgeTransactional(long txID, long ackID) throws Exception
+   {
+      messageJournal.appendDeleteRecordTransactional(txID, ackID);
+   }
+
+
    public long storeHeuristicCompletion(final Xid xid, final boolean isCommit) throws Exception
    {
       long id = generateUniqueID();
@@ -763,6 +808,7 @@
                                                     final PagingManager pagingManager,
                                                     final ResourceManager resourceManager,
                                                     final Map<Long, Queue> queues,
+                                                    Map<Long, QueueBindingInfo> queueInfos,
                                                     final Map<SimpleString, List<Pair<byte[], Long>>> duplicateIDMap) throws Exception
    {
       List<RecordInfo> records = new ArrayList<RecordInfo>();
@@ -912,7 +958,7 @@
 
                   PageTransactionInfo pageTX = pagingManager.getTransaction(pageUpdate.pageTX);
 
-                  pageTX.update(pageUpdate.recods, null, null);
+                  pageTX.onUpdate(pageUpdate.recods, null, null);
                }
                else
                {
@@ -979,6 +1025,29 @@
                resourceManager.putHeuristicCompletion(record.id, encoding.xid, encoding.isCommit);
                break;
             }
+            case ACKNOWLEDGE_CURSOR:
+            {
+               CursorAckRecordEncoding encoding = new CursorAckRecordEncoding();
+               encoding.decode(buff);
+               
+               encoding.position.setRecordID(record.id);
+               
+               QueueBindingInfo queueInfo = queueInfos.get(encoding.queueID);
+               
+               if (queueInfo != null)
+               {
+                  SimpleString address = queueInfo.getAddress();
+                  PagingStore store = pagingManager.getPageStore(address);
+                  PageSubscription cursor = store.getCursorProvier().getSubscription(encoding.queueID);
+                  cursor.reloadACK(encoding.position);
+               }
+               else
+               {
+                  log.warn("Can't find queue " + encoding.queueID + " while reloading ACKNOWLEDGE_CURSOR");
+               }
+               
+               break;
+            }
             default:
             {
                throw new IllegalStateException("Invalid record type " + recordType);
@@ -1475,8 +1544,6 @@
 
                   pageTransactionInfo.decode(buff);
 
-                  pageTransactionInfo.markIncomplete();
-
                   tx.putProperty(TransactionPropertyIndexes.PAGE_TRANSACTION, pageTransactionInfo);
 
                   pagingManager.addTransaction(pageTransactionInfo);
@@ -1513,6 +1580,12 @@
 
                   break;
                }
+               case ACKNOWLEDGE_CURSOR:
+               {
+                  // TODO: implement and test this case
+                  // and make sure the rollback will work well also
+                  break;
+               }
                default:
                {
                   JournalStorageManager.log.warn("InternalError: Record type " + recordType +
@@ -2201,6 +2274,7 @@
       }
 
    }
+   
 
    private static final class AddMessageRecord
    {
@@ -2214,8 +2288,53 @@
       long scheduledDeliveryTime;
 
       int deliveryCount;
+   }
 
-      boolean referenced = false;
+   private static final class CursorAckRecordEncoding implements EncodingSupport
+   {
+      public CursorAckRecordEncoding(final long queueID, final PagePosition position)
+      {
+         this.queueID = queueID;
+         this.position = position;
+      }
+      
+      public CursorAckRecordEncoding()
+      {
+         this.position = new PagePositionImpl();
+      }
+
+      long queueID;
+
+      PagePosition position;
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.EncodingSupport#getEncodeSize()
+       */
+      public int getEncodeSize()
+      {
+         return DataConstants.SIZE_LONG + DataConstants.SIZE_LONG + DataConstants.SIZE_INT;
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.EncodingSupport#encode(org.hornetq.api.core.HornetQBuffer)
+       */
+      public void encode(HornetQBuffer buffer)
+      {
+         buffer.writeLong(queueID);
+         buffer.writeLong(position.getPageNr());
+         buffer.writeInt(position.getMessageNr());
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.journal.EncodingSupport#decode(org.hornetq.api.core.HornetQBuffer)
+       */
+      public void decode(HornetQBuffer buffer)
+      {
+         queueID = buffer.readLong();
+         long pageNR = buffer.readLong();
+         int messageNR = buffer.readInt();
+         this.position = new PagePositionImpl(pageNR, messageNR);
+      }
    }
 
    private class LargeMessageTXFailureCallback implements TransactionFailureCallback
@@ -2254,5 +2373,4 @@
       }
 
    }
-
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/impl/journal/OperationContextImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/impl/journal/OperationContextImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/impl/journal/OperationContextImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -280,8 +280,12 @@
       if (timeout == 0)
       {
          waitCallback.waitCompletion();
+         return true;
       }
-      return waitCallback.waitCompletion(timeout);
+      else
+      {
+         return waitCallback.waitCompletion(timeout);
+      }
    }
 
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/impl/nullpm/NullStorageManager.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/impl/nullpm/NullStorageManager.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/persistence/impl/nullpm/NullStorageManager.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -31,6 +31,7 @@
 import org.hornetq.core.paging.PageTransactionInfo;
 import org.hornetq.core.paging.PagedMessage;
 import org.hornetq.core.paging.PagingManager;
+import org.hornetq.core.paging.cursor.PagePosition;
 import org.hornetq.core.persistence.GroupingInfo;
 import org.hornetq.core.persistence.OperationContext;
 import org.hornetq.core.persistence.QueueBindingInfo;
@@ -267,6 +268,7 @@
                                                     final PagingManager pagingManager,
                                                     final ResourceManager resourceManager,
                                                     final Map<Long, Queue> queues,
+                                                    Map<Long, QueueBindingInfo> queueInfos,
                                                     final Map<SimpleString, List<Pair<byte[], Long>>> duplicateIDMap) throws Exception
    {
       return new JournalLoadInformation();
@@ -450,4 +452,40 @@
    {
    }
 
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#storeCursorAcknowledge(long, org.hornetq.core.paging.cursor.PagePosition)
+    */
+   public void storeCursorAcknowledge(long queueID, PagePosition position)
+   {
+      // TODO Auto-generated method stub
+      
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#storeCursorAcknowledgeTransactional(long, long, org.hornetq.core.paging.cursor.PagePosition)
+    */
+   public void storeCursorAcknowledgeTransactional(long txID, long queueID, PagePosition position)
+   {
+      // TODO Auto-generated method stub
+      
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#deleteCursorAcknowledgeTransactional(long, long)
+    */
+   public void deleteCursorAcknowledgeTransactional(long txID, long ackID) throws Exception
+   {
+      // TODO Auto-generated method stub
+      
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.persistence.StorageManager#updatePageTransaction(org.hornetq.core.paging.PageTransactionInfo, int)
+    */
+   public void updatePageTransaction(PageTransactionInfo pageTransaction, int depage) throws Exception
+   {
+      // TODO Auto-generated method stub
+      
+   }
+
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/AddressManager.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/AddressManager.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/AddressManager.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -25,13 +25,13 @@
  */
 public interface AddressManager
 {
-   boolean addBinding(Binding binding);
+   boolean addBinding(Binding binding) throws Exception;
 
-   Binding removeBinding(SimpleString uniqueName);
+   Binding removeBinding(SimpleString uniqueName) throws Exception;
 
-   Bindings getBindingsForRoutingAddress(SimpleString address);
+   Bindings getBindingsForRoutingAddress(SimpleString address) throws Exception;
 
-   Bindings getMatchingBindings(SimpleString address);
+   Bindings getMatchingBindings(SimpleString address) throws Exception;
 
    void clear();
 

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/Bindings.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/Bindings.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/Bindings.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -15,6 +15,7 @@
 
 import java.util.Collection;
 
+import org.hornetq.core.paging.PagingStore;
 import org.hornetq.core.server.Queue;
 import org.hornetq.core.server.RoutingContext;
 import org.hornetq.core.server.ServerMessage;
@@ -41,4 +42,6 @@
    boolean redistribute(ServerMessage message, Queue originatingQueue, RoutingContext context) throws Exception;
 
    void route(ServerMessage message, RoutingContext context) throws Exception;
+   
+   PagingStore getPagingStore();
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/BindingsFactory.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/BindingsFactory.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/BindingsFactory.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -12,6 +12,8 @@
  */
 package org.hornetq.core.postoffice;
 
+import org.hornetq.api.core.SimpleString;
+
 /**
  * A factory for creating bindings
  *
@@ -19,5 +21,5 @@
  */
 public interface BindingsFactory
 {
-   Bindings createBindings();
+   Bindings createBindings(SimpleString address) throws Exception;
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/PostOffice.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/PostOffice.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/PostOffice.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -47,7 +47,7 @@
 
    Binding getBinding(SimpleString uniqueName);
 
-   Bindings getMatchingBindings(SimpleString address);
+   Bindings getMatchingBindings(SimpleString address) throws Exception;
    
    void route(ServerMessage message, boolean direct) throws Exception;
 

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/BindingsImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/BindingsImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/BindingsImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -27,6 +27,7 @@
 import org.hornetq.core.filter.Filter;
 import org.hornetq.core.logging.Logger;
 import org.hornetq.core.message.impl.MessageImpl;
+import org.hornetq.core.paging.PagingStore;
 import org.hornetq.core.postoffice.Binding;
 import org.hornetq.core.postoffice.Bindings;
 import org.hornetq.core.server.Queue;
@@ -60,10 +61,13 @@
    private volatile boolean routeWhenNoConsumers;
 
    private final GroupingHandler groupingHandler;
+   
+   private final PagingStore pageStore;
 
-   public BindingsImpl(final GroupingHandler groupingHandler)
+   public BindingsImpl(final GroupingHandler groupingHandler, final PagingStore pageStore)
    {
       this.groupingHandler = groupingHandler;
+      this.pageStore = pageStore;
    }
 
    public void setRouteWhenNoConsumers(final boolean routeWhenNoConsumers)
@@ -218,7 +222,12 @@
          return false;
       }
    }
-
+   
+   public PagingStore getPagingStore()
+   {
+      return pageStore;
+   }
+   
    public void route(final ServerMessage message, final RoutingContext context) throws Exception
    {
       boolean routed = false;

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/PostOfficeImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/PostOfficeImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/PostOfficeImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -14,10 +14,13 @@
 package org.hornetq.core.postoffice.impl;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
@@ -47,6 +50,7 @@
 import org.hornetq.core.server.MessageReference;
 import org.hornetq.core.server.Queue;
 import org.hornetq.core.server.QueueFactory;
+import org.hornetq.core.server.RouteContextList;
 import org.hornetq.core.server.RoutingContext;
 import org.hornetq.core.server.ServerMessage;
 import org.hornetq.core.server.impl.RoutingContextImpl;
@@ -58,6 +62,7 @@
 import org.hornetq.core.settings.impl.AddressSettings;
 import org.hornetq.core.transaction.Transaction;
 import org.hornetq.core.transaction.TransactionOperation;
+import org.hornetq.core.transaction.TransactionOperationAbstract;
 import org.hornetq.core.transaction.TransactionPropertyIndexes;
 import org.hornetq.core.transaction.Transaction.State;
 import org.hornetq.core.transaction.impl.TransactionImpl;
@@ -508,13 +513,13 @@
       return binding;
    }
 
-   public Bindings getBindingsForAddress(final SimpleString address)
+   public Bindings getBindingsForAddress(final SimpleString address) throws Exception
    {
       Bindings bindings = addressManager.getBindingsForRoutingAddress(address);
 
       if (bindings == null)
       {
-         bindings = createBindings();
+         bindings = createBindings(address);
       }
 
       return bindings;
@@ -525,7 +530,7 @@
       return addressManager.getBinding(name);
    }
 
-   public Bindings getMatchingBindings(final SimpleString address)
+   public Bindings getMatchingBindings(final SimpleString address) throws Exception
    {
       return addressManager.getMatchingBindings(address);
    }
@@ -606,47 +611,13 @@
          cache.addToCache(duplicateIDBytes, context.getTransaction());
       }
 
-      if (context.getTransaction() == null)
-      {
-         if (message.page())
-         {
-            return;
-         }
-      }
-      else
-      {
-         Transaction tx = context.getTransaction();
-
-         boolean depage = tx.getProperty(TransactionPropertyIndexes.IS_DEPAGE) != null;
-
-         // if the TX paged at least one message on a give address, all the other addresses should also go towards
-         // paging cache now
-         boolean alreadyPaging = false;
-
-         if (tx.isPaging())
-         {
-            alreadyPaging = getPageOperation(tx).isPaging(message.getAddress());
-         }
-
-         if (!depage && message.storeIsPaging() || alreadyPaging)
-         {
-            tx.setPaging(true);
-            getPageOperation(tx).addMessageToPage(message);
-            if (startedTx)
-            {
-               tx.commit();
-            }
-
-            return;
-         }
-      }
-
       Bindings bindings = addressManager.getBindingsForRoutingAddress(address);
 
       if (bindings != null)
       {
          bindings.route(message, context);
       }
+
       if (context.getQueueCount() == 0)
       {
          // Send to DLA if appropriate
@@ -867,89 +838,133 @@
          processRoute(message, context, false);
       }
    }
-
-   private void processRoute(final ServerMessage message, final RoutingContext context, final boolean direct) throws Exception
+   
+   
+   private class PageDelivery extends TransactionOperationAbstract
    {
-      final List<MessageReference> refs = new ArrayList<MessageReference>();
-
-      Transaction tx = context.getTransaction();
-
-      for (Queue queue : context.getNonDurableQueues())
+      private Set<Queue> queues = new HashSet<Queue>();
+      
+      public void addQueues(List<Queue> queueList)
       {
-         MessageReference reference = message.createReference(queue);
-
-         refs.add(reference);
-
-         if (message.containsProperty(Message.HDR_SCHEDULED_DELIVERY_TIME))
+         queues.addAll(queueList);
+      }
+      
+      public void afterCommit(Transaction tx)
+      {
+         // We need to try delivering async after paging, or nothing may start a delivery after paging since nothing is going towards the queues
+         // The queue will try to depage case it's empty
+         for (Queue queue : queues)
          {
-            Long scheduledDeliveryTime = message.getLongProperty(Message.HDR_SCHEDULED_DELIVERY_TIME);
-
-            reference.setScheduledDeliveryTime(scheduledDeliveryTime);
+            queue.deliverAsync();
          }
-
-         message.incrementRefCount();
       }
 
-      Iterator<Queue> iter = context.getDurableQueues().iterator();
-
-      while (iter.hasNext())
+      /* (non-Javadoc)
+       * @see org.hornetq.core.transaction.TransactionOperation#getRelatedMessageReferences()
+       */
+      public List<MessageReference> getRelatedMessageReferences()
       {
-         Queue queue = iter.next();
+         return Collections.emptyList();
+      }
+      
+   }
 
-         MessageReference reference = message.createReference(queue);
+   private void processRoute(final ServerMessage message, final RoutingContext context, final boolean direct) throws Exception
+   {
+      final List<MessageReference> refs = new ArrayList<MessageReference>();
 
-         refs.add(reference);
-
-         if (message.containsProperty(Message.HDR_SCHEDULED_DELIVERY_TIME))
+      Transaction tx = context.getTransaction();
+      
+      
+      for (Map.Entry<SimpleString, RouteContextList> entry: context.getContexListing().entrySet())
+      {
+         PagingStore store = pagingManager.getPageStore(entry.getKey());
+         
+         if (store.page(message, context, entry.getValue()))
          {
-            Long scheduledDeliveryTime = message.getLongProperty(Message.HDR_SCHEDULED_DELIVERY_TIME);
-
-            reference.setScheduledDeliveryTime(scheduledDeliveryTime);
+            
+            // We need to kick delivery so the Queues may check for the cursors case they are empty
+            schedulePageDelivery(tx, entry);
+            continue;
          }
-
-         if (message.isDurable())
+   
+         for (Queue queue : entry.getValue().getNonDurableQueues())
          {
-            int durableRefCount = message.incrementDurableRefCount();
-
-            if (durableRefCount == 1)
+            MessageReference reference = message.createReference(queue);
+   
+            refs.add(reference);
+   
+            if (message.containsProperty(Message.HDR_SCHEDULED_DELIVERY_TIME))
             {
-               if (tx != null)
-               {
-                  storageManager.storeMessageTransactional(tx.getID(), message);
-               }
-               else
-               {
-                  storageManager.storeMessage(message);
-               }
+               Long scheduledDeliveryTime = message.getLongProperty(Message.HDR_SCHEDULED_DELIVERY_TIME);
+   
+               reference.setScheduledDeliveryTime(scheduledDeliveryTime);
             }
-
-            if (tx != null)
+   
+            message.incrementRefCount();
+         }
+   
+         Iterator<Queue> iter = entry.getValue().getDurableQueues().iterator();
+   
+         while (iter.hasNext())
+         {
+            Queue queue = iter.next();
+   
+            MessageReference reference = message.createReference(queue);
+   
+            refs.add(reference);
+   
+            if (message.containsProperty(Message.HDR_SCHEDULED_DELIVERY_TIME))
             {
-               storageManager.storeReferenceTransactional(tx.getID(), queue.getID(), message.getMessageID());
-
-               tx.setContainsPersistent();
+               Long scheduledDeliveryTime = message.getLongProperty(Message.HDR_SCHEDULED_DELIVERY_TIME);
+   
+               reference.setScheduledDeliveryTime(scheduledDeliveryTime);
             }
-            else
+   
+            if (message.isDurable())
             {
-               storageManager.storeReference(queue.getID(), message.getMessageID(), !iter.hasNext());
-            }
-
-            if (message.containsProperty(Message.HDR_SCHEDULED_DELIVERY_TIME))
-            {
+               int durableRefCount = message.incrementDurableRefCount();
+   
+               if (durableRefCount == 1)
+               {
+                  if (tx != null)
+                  {
+                     storageManager.storeMessageTransactional(tx.getID(), message);
+                  }
+                  else
+                  {
+                     storageManager.storeMessage(message);
+                  }
+               }
+   
                if (tx != null)
                {
-                  storageManager.updateScheduledDeliveryTimeTransactional(tx.getID(), reference);
+                  storageManager.storeReferenceTransactional(tx.getID(), queue.getID(), message.getMessageID());
+   
+                  tx.setContainsPersistent();
                }
                else
                {
-                  storageManager.updateScheduledDeliveryTime(reference);
+                  storageManager.storeReference(queue.getID(), message.getMessageID(), !iter.hasNext());
                }
+   
+               if (message.containsProperty(Message.HDR_SCHEDULED_DELIVERY_TIME))
+               {
+                  if (tx != null)
+                  {
+                     storageManager.updateScheduledDeliveryTimeTransactional(tx.getID(), reference);
+                  }
+                  else
+                  {
+                     storageManager.updateScheduledDeliveryTime(reference);
+                  }
+               }
             }
+   
+            message.incrementRefCount();
          }
-
-         message.incrementRefCount();
       }
-
+      
       if (tx != null)
       {
          tx.addOperation(new AddOperation(refs));
@@ -976,6 +991,56 @@
    }
 
    /**
+    * This will kick a delivery async on the queue, so the queue may have a chance to depage messages
+    * @param tx
+    * @param entry
+    */
+   private void schedulePageDelivery(Transaction tx, Map.Entry<SimpleString, RouteContextList> entry)
+   {
+      if (tx != null)
+      {
+         PageDelivery delivery = (PageDelivery)tx.getProperty(TransactionPropertyIndexes.PAGE_DELIVERY);
+         if (delivery == null)
+         {
+            delivery = new PageDelivery();
+            tx.putProperty(TransactionPropertyIndexes.PAGE_DELIVERY, delivery);
+            tx.addOperation(delivery);
+         }
+         
+         delivery.addQueues(entry.getValue().getDurableQueues());
+         delivery.addQueues(entry.getValue().getNonDurableQueues());
+      }
+      else
+      {
+
+         List<Queue> durableQueues = entry.getValue().getDurableQueues();
+         List<Queue> nonDurableQueues = entry.getValue().getNonDurableQueues();
+         
+         final List<Queue> queues = new ArrayList<Queue>(durableQueues.size() + nonDurableQueues.size());
+         
+         queues.addAll(durableQueues);
+         queues.addAll(nonDurableQueues);
+
+         storageManager.afterCompleteOperations(new IOAsyncTask()
+         {
+            
+            public void onError(int errorCode, String errorMessage)
+            {
+            }
+            
+            public void done()
+            {
+               for (Queue queue : queues)
+               {
+                  // in case of paging, we need to kick asynchronous delivery to try delivering
+                  queue.deliverAsync();
+               }
+            }
+         });
+      }
+   }
+
+   /**
     * @param refs
     */
    private void addReferences(final List<MessageReference> refs, final boolean direct)
@@ -1014,27 +1079,6 @@
       return message;
    }
 
-   private final PageMessageOperation getPageOperation(final Transaction tx)
-   {
-      // you could have races on the case two sessions using the same XID
-      // so this whole operation needs to be atomic per TX
-      synchronized (tx)
-      {
-         PageMessageOperation oper = (PageMessageOperation)tx.getProperty(TransactionPropertyIndexes.PAGE_MESSAGES_OPERATION);
-
-         if (oper == null)
-         {
-            oper = new PageMessageOperation();
-
-            tx.putProperty(TransactionPropertyIndexes.PAGE_MESSAGES_OPERATION, oper);
-
-            tx.addOperation(oper);
-         }
-
-         return oper;
-      }
-   }
-
    private class Reaper implements Runnable
    {
       private volatile boolean closed = false;
@@ -1114,189 +1158,6 @@
       }
    }
 
-   private class PageMessageOperation implements TransactionOperation
-   {
-      private final HashMap<SimpleString, Pair<PagingStore, List<ServerMessage>>> pagingData = new HashMap<SimpleString, Pair<PagingStore, List<ServerMessage>>>();
-
-      private Transaction subTX = null;
-
-      void addMessageToPage(final ServerMessage message)
-      {
-         Pair<PagingStore, List<ServerMessage>> pagePair = pagingData.get(message.getAddress());
-         if (pagePair == null)
-         {
-            pagePair = new Pair<PagingStore, List<ServerMessage>>(message.getPagingStore(),
-                                                                  new ArrayList<ServerMessage>());
-            pagingData.put(message.getAddress(), pagePair);
-         }
-
-         pagePair.b.add(message);
-      }
-
-      boolean isPaging(final SimpleString address)
-      {
-         return pagingData.get(address) != null;
-      }
-
-      public void afterCommit(final Transaction tx)
-      {
-         // If part of the transaction goes to the queue, and part goes to paging, we can't let depage start for the
-         // transaction until all the messages were added to the queue
-         // or else we could deliver the messages out of order
-
-         PageTransactionInfo pageTransaction = (PageTransactionInfo)tx.getProperty(TransactionPropertyIndexes.PAGE_TRANSACTION);
-
-         if (pageTransaction != null)
-         {
-            pageTransaction.commit();
-         }
-
-         if (subTX != null)
-         {
-            subTX.afterCommit();
-         }
-      }
-
-      public void afterPrepare(final Transaction tx)
-      {
-         if (subTX != null)
-         {
-            subTX.afterPrepare();
-         }
-      }
-
-      public void afterRollback(final Transaction tx)
-      {
-         PageTransactionInfo pageTransaction = (PageTransactionInfo)tx.getProperty(TransactionPropertyIndexes.PAGE_TRANSACTION);
-
-         if (tx.getState() == State.PREPARED && pageTransaction != null)
-         {
-            pageTransaction.rollback();
-         }
-
-         if (subTX != null)
-         {
-            subTX.afterRollback();
-         }
-      }
-
-      public void beforeCommit(final Transaction tx) throws Exception
-      {
-         if (tx.getState() != Transaction.State.PREPARED)
-         {
-            pageMessages(tx);
-         }
-
-         if (subTX != null)
-         {
-            subTX.beforeCommit();
-         }
-
-      }
-
-      public void beforePrepare(final Transaction tx) throws Exception
-      {
-         pageMessages(tx);
-
-         if (subTX != null)
-         {
-            subTX.beforePrepare();
-         }
-      }
-
-      public void beforeRollback(final Transaction tx) throws Exception
-      {
-         if (subTX != null)
-         {
-            subTX.beforeRollback();
-         }
-      }
-
-      public List<MessageReference> getRelatedMessageReferences()
-      {
-         return null;
-      }
-      
-      private void pageMessages(final Transaction tx) throws Exception
-      {
-         if (!pagingData.isEmpty())
-         {
-            PageTransactionInfo pageTransaction = (PageTransactionInfo)tx.getProperty(TransactionPropertyIndexes.PAGE_TRANSACTION);
-
-            if (pageTransaction == null)
-            {
-               pageTransaction = new PageTransactionInfoImpl(tx.getID());
-
-               tx.putProperty(TransactionPropertyIndexes.PAGE_TRANSACTION, pageTransaction);
-
-               // To avoid a race condition where depage happens before the transaction is completed, we need to inform
-               // the pager about this transaction is being processed
-               pagingManager.addTransaction(pageTransaction);
-            }
-
-            boolean pagingPersistent = false;
-
-            ArrayList<ServerMessage> nonPagedMessages = null;
-
-            for (Pair<PagingStore, List<ServerMessage>> pair : pagingData.values())
-            {
-               
-               if (!pair.a.page(pair.b, tx.getID()))
-               {
-                  if (nonPagedMessages == null)
-                  {
-                     nonPagedMessages = new ArrayList<ServerMessage>();
-                  }
-                  nonPagedMessages.addAll(pair.b);
-               }
-               
-               for (ServerMessage msg : pair.b)
-               {
-                  if (msg.isDurable())
-                  {
-                     pageTransaction.increment();
-                     pagingPersistent = true;
-                  }
-               }
-            }
-
-            if (nonPagedMessages != null)
-            {
-               for (ServerMessage message : nonPagedMessages)
-               {
-                  // This could happen when the PageStore left the pageState
-                  // we create a copy of the transaction so that messages are routed with the same tx ID.
-                  // but we can not use directly the tx as it has already its own set of TransactionOperations
-                  if (subTX == null)
-                  {
-                     subTX = tx.copy();
-                  }
-
-                  route(message, subTX, false);
-
-                  if (subTX.isContainsPersistent())
-                  {
-                     // The route wouldn't be able to update the persistent flag on the main TX
-                     // If we don't do this we would eventually miss a commit record
-                     tx.setContainsPersistent();
-                  }
-               }
-            }
-
-            if (pagingPersistent)
-            {
-               tx.setContainsPersistent();
-               for (Pair<PagingStore, List<ServerMessage>> pair : pagingData.values())
-               {
-                  pair.a.sync();
-               }
-
-               pageTransaction.store(storageManager, pagingManager, tx);
-            }
-         }
-      }
-   }
-
    private class AddOperation implements TransactionOperation
    {
       private final List<MessageReference> refs;
@@ -1353,8 +1214,8 @@
       }
    }
 
-   public Bindings createBindings()
+   public Bindings createBindings(final SimpleString address) throws Exception
    {
-      return new BindingsImpl(server.getGroupingHandler());
+      return new BindingsImpl(server.getGroupingHandler(), pagingManager.getPageStore(address));
    }
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/SimpleAddressManager.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/SimpleAddressManager.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/SimpleAddressManager.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -46,7 +46,7 @@
       this.bindingsFactory = bindingsFactory;
    }
 
-   public boolean addBinding(final Binding binding)
+   public boolean addBinding(final Binding binding) throws Exception
    {
       if (nameMap.putIfAbsent(binding.getUniqueName(), binding) != null)
       {
@@ -56,7 +56,7 @@
       return addMappingInternal(binding.getAddress(), binding);
    }
 
-   public Binding removeBinding(final SimpleString uniqueName)
+   public Binding removeBinding(final SimpleString uniqueName) throws Exception
    {
       Binding binding = nameMap.remove(uniqueName);
 
@@ -70,7 +70,7 @@
       return binding;
    }
 
-   public Bindings getBindingsForRoutingAddress(final SimpleString address)
+   public Bindings getBindingsForRoutingAddress(final SimpleString address) throws Exception
    {
       return mappings.get(address);
    }
@@ -85,11 +85,11 @@
       return nameMap;
    }
 
-   public Bindings getMatchingBindings(final SimpleString address)
+   public Bindings getMatchingBindings(final SimpleString address) throws Exception
    {
       Address add = new AddressImpl(address);
 
-      Bindings bindings = bindingsFactory.createBindings();
+      Bindings bindings = bindingsFactory.createBindings(address);
 
       for (Binding binding : nameMap.values())
       {
@@ -149,7 +149,7 @@
       return theBinding;
    }
 
-   protected boolean addMappingInternal(final SimpleString address, final Binding binding)
+   protected boolean addMappingInternal(final SimpleString address, final Binding binding) throws Exception
    {
       Bindings bindings = mappings.get(address);
 
@@ -157,7 +157,7 @@
 
       if (bindings == null)
       {
-         bindings = bindingsFactory.createBindings();
+         bindings = bindingsFactory.createBindings(address);
 
          prevBindings = mappings.putIfAbsent(address, bindings);
 

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/WildcardAddressManager.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/WildcardAddressManager.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/postoffice/impl/WildcardAddressManager.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -57,7 +57,7 @@
    }
 
    @Override
-   public Bindings getBindingsForRoutingAddress(final SimpleString address)
+   public Bindings getBindingsForRoutingAddress(final SimpleString address) throws Exception
    {
       Bindings bindings = super.getBindingsForRoutingAddress(address);
 
@@ -93,7 +93,7 @@
     * @return true if the address was a new mapping
     */
    @Override
-   public boolean addBinding(final Binding binding)
+   public boolean addBinding(final Binding binding) throws Exception
    {
       boolean exists = super.addBinding(binding);
       if (!exists)
@@ -129,7 +129,7 @@
     * @return true if this was the last mapping for a specific address
     */
    @Override
-   public Binding removeBinding(final SimpleString uniqueName)
+   public Binding removeBinding(final SimpleString uniqueName) throws Exception
    {
       Binding binding = super.removeBinding(uniqueName);
       if (binding != null)
@@ -239,7 +239,7 @@
       }
    }
 
-   private synchronized void removeAndUpdateAddressMap(final Address address)
+   private synchronized void removeAndUpdateAddressMap(final Address address) throws Exception
    {
       // we only remove if there are no bindings left
       Bindings bindings = super.getBindingsForRoutingAddress(address.getAddress());

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/replication/impl/ReplicationEndpointImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/replication/impl/ReplicationEndpointImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/replication/impl/ReplicationEndpointImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -548,7 +548,8 @@
    private void handlePageWrite(final ReplicationPageWriteMessage packet) throws Exception
    {
       PagedMessage pgdMessage = packet.getPagedMessage();
-      ServerMessage msg = pgdMessage.getMessage(storage);
+      pgdMessage.initMessage(storage);
+      ServerMessage msg = pgdMessage.getMessage();
       Page page = getPage(msg.getAddress(), packet.getPageNumber());
       page.write(pgdMessage);
    }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/MessageReference.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/MessageReference.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/MessageReference.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -13,6 +13,8 @@
 
 package org.hornetq.core.server;
 
+import org.hornetq.core.transaction.Transaction;
+
 /**
  * A reference to a message.
  * 
@@ -26,6 +28,9 @@
  */
 public interface MessageReference
 {
+   
+   boolean isPaged();
+   
    ServerMessage getMessage();
 
    MessageReference copy(Queue queue);
@@ -48,6 +53,11 @@
    void decrementDeliveryCount();
 
    Queue getQueue();
+   
+   void acknowledge() throws Exception;
+   
+   void acknowledge(final Transaction tx) throws Exception;
 
+
    void handled();
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/Queue.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/Queue.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/Queue.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -20,6 +20,7 @@
 
 import org.hornetq.api.core.SimpleString;
 import org.hornetq.core.filter.Filter;
+import org.hornetq.core.paging.cursor.PageSubscription;
 import org.hornetq.core.transaction.Transaction;
 
 /**
@@ -38,6 +39,8 @@
    long getID();
 
    Filter getFilter();
+   
+   PageSubscription getPageSubscription();
 
    boolean isDurable();
 

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/QueueFactory.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/QueueFactory.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/QueueFactory.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -15,6 +15,7 @@
 
 import org.hornetq.api.core.SimpleString;
 import org.hornetq.core.filter.Filter;
+import org.hornetq.core.paging.cursor.PageSubscription;
 import org.hornetq.core.postoffice.PostOffice;
 
 /**
@@ -33,6 +34,7 @@
                      final SimpleString address,
                      SimpleString name,
                      Filter filter,
+                     PageSubscription pageSubscription,
                      boolean durable,
                      boolean temporary);
 

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/RouteContextList.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/RouteContextList.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/RouteContextList.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.server;
+
+import java.util.List;
+
+/**
+ * This is a simple datatype containing the list of a routing context
+ *
+ * @author clebertsuconic
+ *
+ *
+ */
+public interface RouteContextList
+{
+   
+   int getNumberOfQueues();
+
+   List<Queue> getDurableQueues();
+   
+   List<Queue> getNonDurableQueues();
+
+}

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/RoutingContext.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/RoutingContext.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/RoutingContext.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -14,13 +14,17 @@
 package org.hornetq.core.server;
 
 import java.util.List;
+import java.util.Map;
 
+import org.hornetq.api.core.Pair;
+import org.hornetq.api.core.SimpleString;
 import org.hornetq.core.transaction.Transaction;
 
 /**
  * A RoutingContext
  *
  * @author Tim Fox
+ * @author Clebert Suconic
  *
  *
  */
@@ -30,14 +34,20 @@
 
    void setTransaction(Transaction transaction);
 
-   void addQueue(Queue queue);
+   void addQueue(SimpleString address, Queue queue);
 
-   List<Queue> getNonDurableQueues();
+   Map<SimpleString, RouteContextList> getContexListing();
+   
+   RouteContextList getContextListing(SimpleString address);
+   
+   List<Queue> getNonDurableQueues(SimpleString address);
 
-   List<Queue> getDurableQueues();
+   List<Queue> getDurableQueues(SimpleString address);
 
    int getQueueCount();
 
    void clear();
+   
+   
 
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/ServerMessage.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/ServerMessage.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/ServerMessage.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -56,10 +56,6 @@
 
    PagingStore getPagingStore();
 
-   boolean page() throws Exception;
-
-   boolean page(long transactionID) throws Exception;
-
    boolean storeIsPaging();
 
    void encodeMessageIDToBuffer();

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/ServerSession.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/ServerSession.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/ServerSession.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -92,7 +92,7 @@
 
    QueueQueryResult executeQueueQuery(SimpleString name) throws Exception;
 
-   BindingQueryResult executeBindingQuery(SimpleString address);
+   BindingQueryResult executeBindingQuery(SimpleString address) throws Exception;
 
    void closeConsumer(long consumerID) throws Exception;
 

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/cluster/impl/RemoteQueueBindingImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/cluster/impl/RemoteQueueBindingImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/cluster/impl/RemoteQueueBindingImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -16,6 +16,7 @@
 import java.nio.ByteBuffer;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -199,12 +200,14 @@
       buff.putLong(remoteQueueID);
 
       message.putBytesProperty(idsHeaderName, ids);
+         
+      List<Queue> durableQueuesOnContext = context.getDurableQueues(address);
 
-      if (!context.getDurableQueues().contains(storeAndForwardQueue))
+      if (!durableQueuesOnContext.contains(storeAndForwardQueue))
       {
          // There can be many remote bindings for the same node, we only want to add the message once to
          // the s & f queue for that node
-         context.addQueue(storeAndForwardQueue);
+         durableQueuesOnContext.add(storeAndForwardQueue);
       }
    }
 

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/HornetQServerImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/HornetQServerImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/HornetQServerImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -21,8 +21,8 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+	import java.util.Map.Entry;
 import java.util.Set;
-import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -61,6 +61,7 @@
 import org.hornetq.core.logging.Logger;
 import org.hornetq.core.management.impl.HornetQServerControlImpl;
 import org.hornetq.core.paging.PagingManager;
+import org.hornetq.core.paging.cursor.PageSubscription;
 import org.hornetq.core.paging.impl.PagingManagerImpl;
 import org.hornetq.core.paging.impl.PagingStoreFactoryNIO;
 import org.hornetq.core.persistence.GroupingInfo;
@@ -163,7 +164,7 @@
    private volatile QueueFactory queueFactory;
 
    private volatile PagingManager pagingManager;
-
+ 
    private volatile PostOffice postOffice;
 
    private volatile ExecutorService threadPool;
@@ -712,6 +713,8 @@
       }
 
       Queue queue = (Queue)binding.getBindable();
+      
+      queue.getPageSubscription().close();
 
       if (queue.getConsumerCount() != 0)
       {
@@ -1113,6 +1116,8 @@
          deploymentManager.start();
       }
 
+      pagingManager.processReload();
+      
       pagingManager.resumeDepages();
 
       final ServerInfo dumper = new ServerInfo(this, pagingManager);
@@ -1188,15 +1193,21 @@
       setNodeID();
 
       Map<Long, Queue> queues = new HashMap<Long, Queue>();
+      Map<Long, QueueBindingInfo> queueBindingInfosMap = new HashMap<Long, QueueBindingInfo>();
 
       for (QueueBindingInfo queueBindingInfo : queueBindingInfos)
       {
+         queueBindingInfosMap.put(queueBindingInfo.getId(), queueBindingInfo);
+         
          Filter filter = FilterImpl.createFilter(queueBindingInfo.getFilterString());
 
+         PageSubscription subscription = pagingManager.getPageStore(queueBindingInfo.getAddress()).getCursorProvier().createSubscription(queueBindingInfo.getId(), filter, true);
+         
          Queue queue = queueFactory.createQueue(queueBindingInfo.getId(),
                                                 queueBindingInfo.getAddress(),
                                                 queueBindingInfo.getQueueName(),
                                                 filter,
+                                                subscription,
                                                 true,
                                                 false);
 
@@ -1208,6 +1219,8 @@
 
          managementService.registerAddress(queueBindingInfo.getAddress());
          managementService.registerQueue(queue, queueBindingInfo.getAddress(), storageManager);
+         
+         
       }
 
       for (GroupingInfo groupingInfo : groupingInfos)
@@ -1226,6 +1239,7 @@
                                                          pagingManager,
                                                          resourceManager,
                                                          queues,
+                                                         queueBindingInfosMap,
                                                          duplicateIDMap);
 
       for (Map.Entry<SimpleString, List<Pair<byte[], Long>>> entry : duplicateIDMap.entrySet())
@@ -1328,11 +1342,16 @@
       }
 
       Filter filter = FilterImpl.createFilter(filterString);
+      
+      long queueID = storageManager.generateUniqueID();
 
-      final Queue queue = queueFactory.createQueue(storageManager.generateUniqueID(),
+      PageSubscription pageSubscription = pagingManager.getPageStore(address).getCursorProvier().createSubscription(queueID, filter, durable);
+
+      final Queue queue = queueFactory.createQueue(queueID,
                                                    address,
                                                    queueName,
                                                    filter,
+                                                   pageSubscription,
                                                    durable,
                                                    temporary);
 

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/LastValueQueue.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/LastValueQueue.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/LastValueQueue.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -21,6 +21,7 @@
 import org.hornetq.api.core.SimpleString;
 import org.hornetq.core.filter.Filter;
 import org.hornetq.core.logging.Logger;
+import org.hornetq.core.paging.cursor.PageSubscription;
 import org.hornetq.core.persistence.StorageManager;
 import org.hornetq.core.postoffice.PostOffice;
 import org.hornetq.core.server.MessageReference;
@@ -28,6 +29,7 @@
 import org.hornetq.core.server.ServerMessage;
 import org.hornetq.core.settings.HierarchicalRepository;
 import org.hornetq.core.settings.impl.AddressSettings;
+import org.hornetq.core.transaction.Transaction;
 
 /**
  * A queue that will discard messages if a newer message with the same MessageImpl.HDR_LAST_VALUE_NAME property value.
@@ -49,6 +51,7 @@
                          final SimpleString address,
                          final SimpleString name,
                          final Filter filter,
+                         final PageSubscription pageSubscription,
                          final boolean durable,
                          final boolean temporary,
                          final ScheduledExecutorService scheduledExecutor,
@@ -61,6 +64,7 @@
             address,
             name,
             filter,
+            pageSubscription,
             durable,
             temporary,
             scheduledExecutor,
@@ -89,7 +93,7 @@
 
             try
             {
-               super.acknowledge(oldRef);
+               oldRef.acknowledge();
             }
             catch (Exception e)
             {
@@ -225,5 +229,26 @@
       {
          ref.setScheduledDeliveryTime(scheduledDeliveryTime);
       }
+      
+      public boolean isPaged()
+      {
+         return false;
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.server.MessageReference#acknowledge(org.hornetq.core.server.MessageReference)
+       */
+      public void acknowledge() throws Exception
+      {
+         ref.acknowledge();
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.server.MessageReference#acknowledge(org.hornetq.core.transaction.Transaction, org.hornetq.core.server.MessageReference)
+       */
+      public void acknowledge(Transaction tx) throws Exception
+      {
+         ref.acknowledge(tx);
+      }
    }
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/MessageReferenceImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/MessageReferenceImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/MessageReferenceImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -17,6 +17,7 @@
 import org.hornetq.core.server.MessageReference;
 import org.hornetq.core.server.Queue;
 import org.hornetq.core.server.ServerMessage;
+import org.hornetq.core.transaction.Transaction;
 import org.hornetq.utils.MemorySize;
 
 /**
@@ -144,7 +145,29 @@
    {
       queue.referenceHandled();
    }
+   
+   public boolean isPaged()
+   {
+      return false;
+   }
 
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.MessageReference#acknowledge(org.hornetq.core.server.MessageReference)
+    */
+   public void acknowledge() throws Exception
+   {
+      queue.acknowledge(this);
+   }
+
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.MessageReference#acknowledge(org.hornetq.core.transaction.Transaction, org.hornetq.core.server.MessageReference)
+    */
+   public void acknowledge(Transaction tx) throws Exception
+   {
+      queue.acknowledge(tx, this);
+   }
+
+
    // Public --------------------------------------------------------
 
    @Override
@@ -154,7 +177,6 @@
              "]:" +
              (getMessage().isDurable() ? "RELIABLE" : "NON-RELIABLE");
    }
-
    // Package protected ---------------------------------------------
 
    // Protected -----------------------------------------------------

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/QueueFactoryImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/QueueFactoryImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/QueueFactoryImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -17,6 +17,7 @@
 
 import org.hornetq.api.core.SimpleString;
 import org.hornetq.core.filter.Filter;
+import org.hornetq.core.paging.cursor.PageSubscription;
 import org.hornetq.core.persistence.StorageManager;
 import org.hornetq.core.postoffice.PostOffice;
 import org.hornetq.core.server.Queue;
@@ -69,6 +70,7 @@
                             final SimpleString address,
                             final SimpleString name,
                             final Filter filter,
+                            final PageSubscription pageSubscription,
                             final boolean durable,
                             final boolean temporary)
    {
@@ -81,6 +83,7 @@
                                     address,
                                     name,
                                     filter,
+                                    pageSubscription,
                                     durable,
                                     temporary,
                                     scheduledExecutor,
@@ -95,6 +98,7 @@
                                address,
                                name,
                                filter,
+                               pageSubscription,
                                durable,
                                temporary,
                                scheduledExecutor,

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/QueueImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/QueueImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/QueueImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -32,6 +32,8 @@
 import org.hornetq.api.core.SimpleString;
 import org.hornetq.core.filter.Filter;
 import org.hornetq.core.logging.Logger;
+import org.hornetq.core.paging.cursor.PageSubscription;
+import org.hornetq.core.paging.cursor.PagedReference;
 import org.hornetq.core.persistence.StorageManager;
 import org.hornetq.core.postoffice.Bindings;
 import org.hornetq.core.postoffice.PostOffice;
@@ -89,6 +91,10 @@
    private final boolean temporary;
 
    private final PostOffice postOffice;
+   
+   private final PageSubscription pageSubscription;
+   
+   private final LinkedListIterator<PagedReference> pageIterator;
 
    private final ConcurrentLinkedQueue<MessageReference> concurrentQueue = new ConcurrentLinkedQueue<MessageReference>();
 
@@ -106,6 +112,8 @@
 
    private final Runnable deliverRunner = new DeliverRunner();
 
+   private final Runnable depageRunner = new DepageRunner();
+
    private final StorageManager storageManager;
 
    private final HierarchicalRepository<AddressSettings> addressSettingsRepository;
@@ -141,11 +149,39 @@
    private volatile boolean checkDirect;
 
    private volatile boolean directDeliver = true;
+   
+   public QueueImpl(final long id,
+                    final SimpleString address,
+                    final SimpleString name,
+                    final Filter filter,
+                    final boolean durable,
+                    final boolean temporary,
+                    final ScheduledExecutorService scheduledExecutor,
+                    final PostOffice postOffice,
+                    final StorageManager storageManager,
+                    final HierarchicalRepository<AddressSettings> addressSettingsRepository,
+                    final Executor executor)
+   {
+      this(id,
+          address,
+          name,
+          filter,
+          null,
+          durable,
+          temporary,
+          scheduledExecutor,
+          postOffice,
+          storageManager,
+          addressSettingsRepository,
+          executor);
+   }
 
+
    public QueueImpl(final long id,
                     final SimpleString address,
                     final SimpleString name,
                     final Filter filter,
+                    final PageSubscription pageSubscription,
                     final boolean durable,
                     final boolean temporary,
                     final ScheduledExecutorService scheduledExecutor,
@@ -161,6 +197,8 @@
       this.name = name;
 
       this.filter = filter;
+      
+      this.pageSubscription = pageSubscription;
 
       this.durable = durable;
 
@@ -184,6 +222,16 @@
       {
          expiryAddress = null;
       }
+      
+      if (pageSubscription != null)
+      {
+         pageSubscription.setQueue(this);
+         this.pageIterator = pageSubscription.iterator();
+      }
+      else
+      {
+         this.pageIterator = null;
+      }
 
       this.executor = executor;
 
@@ -219,7 +267,7 @@
 
    public void route(final ServerMessage message, final RoutingContext context) throws Exception
    {
-      context.addQueue(this);
+      context.addQueue(address, this);
    }
 
    // Queue implementation ----------------------------------------------------------------------------------------
@@ -249,6 +297,11 @@
       return id;
    }
 
+   public PageSubscription getPageSubscription()
+   {
+      return pageSubscription;
+   }
+   
    public Filter getFilter()
    {
       return filter;
@@ -301,7 +354,7 @@
       // We don't recompute it on every delivery since executing isEmpty is expensive for a ConcurrentQueue
       if (checkDirect)
       {
-         if (direct && !directDeliver && concurrentQueue.isEmpty() && messageReferences.isEmpty())
+         if (direct && !directDeliver && concurrentQueue.isEmpty() && messageReferences.isEmpty() && !pageIterator.hasNext() && !pageSubscription.isPaging())
          {
             // We must block on the executor to ensure any async deliveries have completed or we might get out of order
             // deliveries
@@ -627,32 +680,46 @@
 
    public void acknowledge(final MessageReference ref) throws Exception
    {
-      ServerMessage message = ref.getMessage();
-
-      boolean durableRef = message.isDurable() && durable;
-
-      if (durableRef)
+      if (ref.isPaged())
       {
-         storageManager.storeAcknowledge(id, message.getMessageID());
+         pageSubscription.ack((PagedReference)ref);
       }
+      else
+      {
+         ServerMessage message = ref.getMessage();
+   
+         boolean durableRef = message.isDurable() && durable;
+   
+         if (durableRef)
+         {
+            storageManager.storeAcknowledge(id, message.getMessageID());
+         }
+         postAcknowledge(ref);
+      }
 
-      postAcknowledge(ref);
    }
 
    public void acknowledge(final Transaction tx, final MessageReference ref) throws Exception
    {
-      ServerMessage message = ref.getMessage();
-
-      boolean durableRef = message.isDurable() && durable;
-
-      if (durableRef)
+      if (ref.isPaged())
       {
-         storageManager.storeAcknowledgeTransactional(tx.getID(), id, message.getMessageID());
-
-         tx.setContainsPersistent();
+         pageSubscription.ackTx(tx, (PagedReference)ref);
       }
-
-      getRefsOperation(tx).addAck(ref);
+      else
+      {
+         ServerMessage message = ref.getMessage();
+   
+         boolean durableRef = message.isDurable() && durable;
+   
+         if (durableRef)
+         {
+            storageManager.storeAcknowledgeTransactional(tx.getID(), id, message.getMessageID());
+   
+            tx.setContainsPersistent();
+         }
+   
+         getRefsOperation(tx).addAck(ref);
+      }
    }
 
    public void reacknowledge(final Transaction tx, final MessageReference ref) throws Exception
@@ -1187,7 +1254,49 @@
             pos = 0;
          }
       }
+      
+      if (messageReferences.size() == 0 && pageIterator.hasNext())
+      {
+         scheduleDepage();
+      }
    }
+   
+   private void scheduleDepage()
+   {
+      executor.execute(depageRunner);
+   }
+   
+   private void depage()
+   {
+      if (paused || consumerList.isEmpty())
+      {
+         return;
+      }
+      
+      int msgsToDeliver = MAX_DELIVERIES_IN_LOOP - (messageReferences.size() + getScheduledCount() + concurrentQueue.size());
+      
+      if (msgsToDeliver > 0)
+      {
+         //System.out.println("Depaging " + msgsToDeliver + " messages");
+         //System.out.println("Depage "  + msgsToDeliver + " now.. there are msgRef = " + messageReferences.size() + " scheduled = " + getScheduledCount() + " concurrentQueue.size() = " + concurrentQueue.size());
+   
+         int nmessages = 0;
+         while (nmessages < msgsToDeliver && pageIterator.hasNext())
+         {
+            nmessages ++;
+            addTail(pageIterator.next(), false);
+            pageIterator.remove();
+         }
+         
+         //System.out.println("Depaged " + nmessages);
+      }
+//      else
+//      {
+//         System.out.println("Depaging not being done now.. there are msgRef = " + messageReferences.size() + " scheduled = " + getScheduledCount() + " concurrentQueue.size() = " + concurrentQueue.size());
+//      }
+      
+      deliverAsync();
+   }
 
    private void internalAddRedistributor(final Executor executor)
    {
@@ -1212,7 +1321,8 @@
    {
       ServerMessage message = reference.getMessage();
 
-      if (message.isDurable() && durable)
+      // TODO: DeliveryCount on paging
+      if (message.isDurable() && durable && !reference.isPaged())
       {
          storageManager.updateDeliveryCount(reference);
       }
@@ -1682,6 +1792,21 @@
       }
    }
 
+   private class DepageRunner implements Runnable
+   {
+      public void run()
+      {
+         try
+         {
+            depage();
+         }
+         catch (Exception e)
+         {
+            log.error("Failed to deliver", e);
+         }
+      }
+   }
+
    private class ConcurrentPoller implements Runnable
    {
       public void run()

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/RoutingContextImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/RoutingContextImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/RoutingContextImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -14,9 +14,15 @@
 package org.hornetq.core.server.impl;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 
+import org.hornetq.api.core.Pair;
+import org.hornetq.api.core.SimpleString;
 import org.hornetq.core.server.Queue;
+import org.hornetq.core.server.RouteContextList;
 import org.hornetq.core.server.RoutingContext;
 import org.hornetq.core.transaction.Transaction;
 
@@ -29,10 +35,10 @@
  */
 public class RoutingContextImpl implements RoutingContext
 {
-   private final List<Queue> nonDurableQueues = new ArrayList<Queue>(1);
+   
+   // The pair here is Durable and NonDurable
+   private Map<SimpleString, RouteContextList> map = new HashMap<SimpleString, RouteContextList>();
 
-   private final List<Queue> durableQueues = new ArrayList<Queue>(1);
-
    private Transaction transaction;
 
    private int queueCount;
@@ -41,35 +47,42 @@
    {
       this.transaction = transaction;
    }
-
+   
    public void clear()
    {
       transaction = null;
 
-      nonDurableQueues.clear();
-
-      durableQueues.clear();
-
+      map.clear();
+      
       queueCount = 0;
    }
 
-   public void addQueue(final Queue queue)
+   public void addQueue(final SimpleString address, final Queue queue)
    {
+
+      RouteContextList listing = getContextListing(address);
+      
       if (queue.isDurable())
       {
-         durableQueues.add(queue);
+         listing.getDurableQueues().add(queue);
       }
       else
       {
-         nonDurableQueues.add(queue);
+         listing.getNonDurableQueues().add(queue);
       }
 
       queueCount++;
    }
-
-   public void addDurableQueue(final Queue queue)
+   
+   public RouteContextList getContextListing(SimpleString address)
    {
-      durableQueues.add(queue);
+      RouteContextList listing = map.get(address);
+      if (listing == null)
+      {
+         listing = new ContextListing();
+         map.put(address, listing);
+      }
+      return listing;
    }
 
    public Transaction getTransaction()
@@ -82,14 +95,14 @@
       transaction = tx;
    }
 
-   public List<Queue> getNonDurableQueues()
+   public List<Queue> getNonDurableQueues(SimpleString address)
    {
-      return nonDurableQueues;
+      return getContextListing(address).getNonDurableQueues();
    }
 
-   public List<Queue> getDurableQueues()
+   public List<Queue> getDurableQueues(SimpleString address)
    {
-      return durableQueues;
+      return getContextListing(address).getDurableQueues();
    }
 
    public int getQueueCount()
@@ -97,4 +110,41 @@
       return queueCount;
    }
 
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.RoutingContext#getAddresses()
+    */
+   public Map<SimpleString, RouteContextList> getContexListing()
+   {
+      return this.map;
+   }
+   
+   
+   private class ContextListing implements RouteContextList
+   {
+      private List<Queue> durableQueue = new ArrayList<Queue>(1);
+      
+      private List<Queue> nonDurableQueue = new ArrayList<Queue>(1);
+      
+      public int getNumberOfQueues()
+      {
+         return durableQueue.size() + nonDurableQueue.size();
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.server.RouteContextList#getDurableQueues()
+       */
+      public List<Queue> getDurableQueues()
+      {
+         return durableQueue;
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.server.RouteContextList#getNonDurableQueues()
+       */
+      public List<Queue> getNonDurableQueues()
+      {
+         return nonDurableQueue;
+      }
+   }
+
 }

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/ServerConsumerImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/ServerConsumerImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/ServerConsumerImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -553,11 +553,11 @@
 
          if (autoCommitAcks || tx == null)
          {
-            ref.getQueue().acknowledge(ref);
+            ref.acknowledge();
          }
          else
          {
-            ref.getQueue().acknowledge(tx, ref);
+            ref.acknowledge(tx);
          }
       }
       while (ref.getMessage().getMessageID() != messageID);

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/ServerMessageImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/ServerMessageImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/ServerMessageImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -249,30 +249,6 @@
       return pagingStore;
    }
 
-   public boolean page() throws Exception
-   {
-      if (pagingStore != null)
-      {
-         return pagingStore.page(this);
-      }
-      else
-      {
-         return false;
-      }
-   }
-
-   public boolean page(final long transactionID) throws Exception
-   {
-      if (pagingStore != null)
-      {
-         return pagingStore.page(Arrays.asList((ServerMessage)this), transactionID);
-      }
-      else
-      {
-         return false;
-      }
-   }
-
    public boolean storeIsPaging()
    {
       if (pagingStore != null)

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/ServerSessionImpl.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/ServerSessionImpl.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/ServerSessionImpl.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -485,7 +485,7 @@
       return response;
    }
 
-   public BindingQueryResult executeBindingQuery(final SimpleString address)
+   public BindingQueryResult executeBindingQuery(final SimpleString address) throws Exception
    {
       if (address == null)
       {

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/transaction/TransactionOperationAbstract.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/transaction/TransactionOperationAbstract.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/transaction/TransactionOperationAbstract.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.core.transaction;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.hornetq.core.server.MessageReference;
+
+/**
+ * Just a helper, when you don't want to implement all the methods on a transaction operation.
+ *
+ * @author clebertsuconic
+ *
+ *
+ */
+public abstract class TransactionOperationAbstract implements TransactionOperation
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+   public void beforePrepare(Transaction tx) throws Exception
+   {
+
+   }
+
+   /** After prepare shouldn't throw any exception. Any verification has to be done on before prepare */
+   public void afterPrepare(Transaction tx)
+   {
+
+   }
+
+   public void beforeCommit(Transaction tx) throws Exception
+   {
+   }
+
+   /** After commit shouldn't throw any exception. Any verification has to be done on before commit */
+   public void afterCommit(Transaction tx)
+   {
+   }
+
+   public void beforeRollback(Transaction tx) throws Exception
+   {
+   }
+
+   /** After rollback shouldn't throw any exception. Any verification has to be done on before rollback */
+   public void afterRollback(Transaction tx)
+   {
+   }
+   
+   /* (non-Javadoc)
+    * @see org.hornetq.core.transaction.TransactionOperation#getRelatedMessageReferences()
+    */
+   public List<MessageReference> getRelatedMessageReferences()
+   {
+      return Collections.emptyList();
+   }
+   
+
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Modified: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/transaction/TransactionPropertyIndexes.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/transaction/TransactionPropertyIndexes.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/transaction/TransactionPropertyIndexes.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -24,11 +24,14 @@
  */
 public class TransactionPropertyIndexes
 {
-   public static final int IS_DEPAGE = 3;
 
+   public static final int PAGE_TRANSACTION_UPDATE = 4;
+   
    public static final int PAGE_TRANSACTION = 5;
 
    public static final int REFS_OPERATION = 6;
 
-   public static final int PAGE_MESSAGES_OPERATION = 7;
+   public static final int PAGE_DELIVERY = 7;
+   
+   public static final int PAGE_CURSOR_POSITIONS = 8;
 }

Added: branches/Branch_New_Paging_preMerge/src/main/org/hornetq/utils/SoftValueHashMap.java
===================================================================
--- branches/Branch_New_Paging_preMerge/src/main/org/hornetq/utils/SoftValueHashMap.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/utils/SoftValueHashMap.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.utils;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A SoftValueConcurrentHashMap
+ *
+ * @author <a href="mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class SoftValueHashMap<K, V> implements Map<K, V>
+{
+   // The soft references that are already good.
+   // too bad there's no way to override the queue method on ReferenceQueue, so I wouldn't need this
+   private final ReferenceQueue<V> refQueue = new ReferenceQueue<V>();
+
+   private final Map<K, AggregatedSoftReference> mapDelegate = new HashMap<K, AggregatedSoftReference>();
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   /**
+    * @return
+    * @see java.util.Map#size()
+    */
+   public int size()
+   {
+      processQueue();
+      return mapDelegate.size();
+   }
+
+   /**
+    * @return
+    * @see java.util.Map#isEmpty()
+    */
+   public boolean isEmpty()
+   {
+      processQueue();
+      return mapDelegate.isEmpty();
+   }
+
+   /**
+    * @param key
+    * @return
+    * @see java.util.Map#containsKey(java.lang.Object)
+    */
+   public boolean containsKey(final Object key)
+   {
+      processQueue();
+      return mapDelegate.containsKey(key);
+   }
+
+   /**
+    * @param value
+    * @return
+    * @see java.util.Map#containsValue(java.lang.Object)
+    */
+   public boolean containsValue(final Object value)
+   {
+      processQueue();
+      for (AggregatedSoftReference valueIter : mapDelegate.values())
+      {
+         V valueElement = valueIter.get();
+         if (valueElement != null && value.equals(valueElement))
+         {
+            return true;
+         }
+
+      }
+      return false;
+   }
+
+   /**
+    * @param key
+    * @return
+    * @see java.util.Map#get(java.lang.Object)
+    */
+   public V get(final Object key)
+   {
+      processQueue();
+      AggregatedSoftReference value = mapDelegate.get(key);
+      if (value != null)
+      {
+         return value.get();
+      }
+      else
+      {
+         return null;
+      }
+   }
+
+   /**
+    * @param key
+    * @param value
+    * @return
+    * @see java.util.Map#put(java.lang.Object, java.lang.Object)
+    */
+   public V put(final K key, final V value)
+   {
+      processQueue();
+      AggregatedSoftReference refPut = mapDelegate.put(key, createReference(key, value));
+      if (refPut != null)
+      {
+         return refPut.get();
+      }
+      else
+      {
+         return null;
+      }
+   }
+
+   /**
+    * @param key
+    * @return
+    * @see java.util.Map#remove(java.lang.Object)
+    */
+   public V remove(final Object key)
+   {
+      processQueue();
+      AggregatedSoftReference ref = mapDelegate.remove(key);
+      if (ref != null)
+      {
+         return ref.get();
+      }
+      else
+      {
+         return null;
+      }
+   }
+
+   /**
+    * @param m
+    * @see java.util.Map#putAll(java.util.Map)
+    */
+   public void putAll(final Map<? extends K, ? extends V> m)
+   {
+      processQueue();
+      for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
+      {
+         put(e.getKey(), e.getValue());
+      }
+   }
+
+   /**
+    * 
+    * @see java.util.Map#clear()
+    */
+   public void clear()
+   {
+      mapDelegate.clear();
+   }
+
+   /**
+    * @return
+    * @see java.util.Map#keySet()
+    */
+   public Set<K> keySet()
+   {
+      processQueue();
+      return mapDelegate.keySet();
+   }
+
+   /**
+    * @return
+    * @see java.util.Map#values()
+    */
+   public Collection<V> values()
+   {
+      processQueue();
+      ArrayList<V> list = new ArrayList<V>();
+
+      for (AggregatedSoftReference refs : mapDelegate.values())
+      {
+         V value = refs.get();
+         if (value != null)
+         {
+            list.add(value);
+         }
+      }
+
+      return list;
+   }
+
+   /**
+    * @return
+    * @see java.util.Map#entrySet()
+    */
+   public Set<java.util.Map.Entry<K, V>> entrySet()
+   {
+      processQueue();
+      HashSet<Map.Entry<K, V>> set = new HashSet<Map.Entry<K, V>>();
+      for (Map.Entry<K, AggregatedSoftReference> pair : mapDelegate.entrySet())
+      {
+         V value = pair.getValue().get();
+         if (value != null)
+         {
+            set.add(new EntryElement<K,V>(pair.getKey(), value));
+         }
+      }
+      return set;
+   }
+
+   /**
+    * @param o
+    * @return
+    * @see java.util.Map#equals(java.lang.Object)
+    */
+   @Override
+   public boolean equals(final Object o)
+   {
+      processQueue();
+      return mapDelegate.equals(o);
+   }
+
+   /**
+    * @return
+    * @see java.util.Map#hashCode()
+    */
+   @Override
+   public int hashCode()
+   {
+      return mapDelegate.hashCode();
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   @SuppressWarnings("unchecked")
+   private void processQueue()
+   {
+      AggregatedSoftReference ref = null;
+      while ((ref = (AggregatedSoftReference)this.refQueue.poll()) != null)
+      {
+         mapDelegate.remove(ref.key);
+      }
+   }
+
+   private AggregatedSoftReference createReference(final K key, final V value)
+   {
+      AggregatedSoftReference ref = new AggregatedSoftReference(key, value);
+      return ref;
+   }
+
+   // Inner classes -------------------------------------------------
+
+   class AggregatedSoftReference extends SoftReference<V>
+   {
+      final K key;
+
+      public AggregatedSoftReference(final K key, final V referent)
+      {
+         super(referent, refQueue);
+         this.key = key;
+      }
+   }
+
+   static final class EntryElement<K, V> implements Map.Entry<K, V>
+   {
+      final K key;
+
+      volatile V value;
+
+      EntryElement(final K key, final V value)
+      {
+         this.key = key;
+         this.value = value;
+      }
+
+      /* (non-Javadoc)
+       * @see java.util.Map.Entry#getKey()
+       */
+      public K getKey()
+      {
+         return key;
+      }
+
+      /* (non-Javadoc)
+       * @see java.util.Map.Entry#getValue()
+       */
+      public V getValue()
+      {
+         return value;
+      }
+
+      /* (non-Javadoc)
+       * @see java.util.Map.Entry#setValue(java.lang.Object)
+       */
+      public V setValue(final V value)
+      {
+         this.value = value;
+         return value;
+      }
+   }
+
+}

Modified: branches/Branch_New_Paging_preMerge/tests/jms-tests/src/org/hornetq/jms/tests/BrowserTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/jms-tests/src/org/hornetq/jms/tests/BrowserTest.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/jms-tests/src/org/hornetq/jms/tests/BrowserTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -26,6 +26,12 @@
 import javax.jms.Session;
 import javax.jms.TextMessage;
 
+import org.hornetq.api.core.HornetQException;
+import org.hornetq.api.core.client.ClientConsumer;
+import org.hornetq.api.core.client.ClientMessage;
+import org.hornetq.api.core.client.ClientSession;
+import org.hornetq.api.core.client.MessageHandler;
+import org.hornetq.jms.client.HornetQConnectionFactory;
 import org.hornetq.jms.tests.util.ProxyAssertSupport;
 
 /**
@@ -109,8 +115,8 @@
          }
       }
    }
-
-   public void testBrowse() throws Exception
+   
+   public void testBrowse2() throws Exception
    {
       Connection conn = null;
 
@@ -121,59 +127,75 @@
          Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
 
          MessageProducer producer = session.createProducer(HornetQServerTestCase.queue1);
+         
+         HornetQConnectionFactory cf = (HornetQConnectionFactory) getConnectionFactory();
 
-         final int numMessages = 10;
+         ClientSession coreSession = cf.getCoreFactory().createSession(true, true);
 
-         for (int i = 0; i < numMessages; i++)
+         coreSession.start();
+         
+         ClientConsumer browser = coreSession.createConsumer("jms.queue.Queue1", true);
+       
+         conn.start();
+
+         Message m = session.createMessage();
+         m.setIntProperty("cnt", 0);
+         producer.send(m);
+         
+          
+         assertNotNull(browser.receive(5000));
+         
+         Thread.sleep(5000);
+         
+         coreSession.close();
+         
+         
+         System.out.println("Draining destination...");
+         drainDestination(getConnectionFactory(), queue1);
+         
+      }
+      finally
+      {
+         if (conn != null)
          {
-            Message m = session.createMessage();
-            m.setIntProperty("cnt", i);
-            producer.send(m);
+            conn.close();
          }
+      }
+   }
 
+   public void testBrowse() throws Exception
+   {
+      Connection conn = null;
+
+      try
+      {
+         conn = getConnectionFactory().createConnection();
+
+         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+         MessageProducer producer = session.createProducer(HornetQServerTestCase.queue1);
+
          QueueBrowser browser = session.createBrowser(HornetQServerTestCase.queue1);
 
          ProxyAssertSupport.assertEquals(browser.getQueue(), HornetQServerTestCase.queue1);
 
          ProxyAssertSupport.assertNull(browser.getMessageSelector());
 
-         Enumeration en = browser.getEnumeration();
+         Enumeration<Message> en = (Enumeration<Message>)browser.getEnumeration();
 
-         int count = 0;
-         while (en.hasMoreElements())
-         {
-            en.nextElement();
-            count++;
-         }
-
-         ProxyAssertSupport.assertEquals(numMessages, count);
-
-         MessageConsumer mc = session.createConsumer(HornetQServerTestCase.queue1);
-
          conn.start();
 
-         for (int i = 0; i < numMessages; i++)
-         {
-            Message m = mc.receive();
-            ProxyAssertSupport.assertNotNull(m);
-         }
-
-         browser = session.createBrowser(HornetQServerTestCase.queue1);
-         en = browser.getEnumeration();
-
-         log.info("browsing");
-
-         count = 0;
-         while (en.hasMoreElements())
-         {
-            Message mess = (Message)en.nextElement();
-            log.info("message:" + mess);
-            count++;
-         }
-
-         log.trace("Received " + count + " messages");
-
-         ProxyAssertSupport.assertEquals(0, count);
+         Message m = session.createMessage();
+         m.setIntProperty("cnt", 0);
+         producer.send(m);
+         Message m2 = en.nextElement();
+         
+         assertNotNull(m2);
+         
+         
+         System.out.println("Draining destination...");
+         drainDestination(getConnectionFactory(), queue1);
+         
       }
       finally
       {
@@ -204,19 +226,6 @@
             m.setIntProperty("test_counter", i + 1);
             producer.send(m);
          }
-
-         QueueBrowser browser = session.createBrowser(HornetQServerTestCase.queue1, "test_counter > 30");
-
-         Enumeration en = browser.getEnumeration();
-         int count = 0;
-         while (en.hasMoreElements())
-         {
-            Message m = (Message)en.nextElement();
-            int testCounter = m.getIntProperty("test_counter");
-            ProxyAssertSupport.assertTrue(testCounter > 30);
-            count++;
-         }
-         ProxyAssertSupport.assertEquals(70, count);
       }
       finally
       {

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/concurrent/server/impl/QueueTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/concurrent/server/impl/QueueTest.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/concurrent/server/impl/QueueTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -65,6 +65,7 @@
                                              new SimpleString("address1"),
                                              new SimpleString("queue1"),
                                              null,
+                                             null,
                                              false,
                                              false);
 

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/client/PagingTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/client/PagingTest.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/client/PagingTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -17,12 +17,10 @@
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
-import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -42,11 +40,9 @@
 import org.hornetq.core.config.DivertConfiguration;
 import org.hornetq.core.journal.SequentialFileFactory;
 import org.hornetq.core.logging.Logger;
-import org.hornetq.core.paging.Page;
 import org.hornetq.core.paging.PagingManager;
 import org.hornetq.core.paging.PagingStore;
 import org.hornetq.core.paging.PagingStoreFactory;
-import org.hornetq.core.paging.impl.PageImpl;
 import org.hornetq.core.paging.impl.PagingManagerImpl;
 import org.hornetq.core.paging.impl.PagingStoreFactoryNIO;
 import org.hornetq.core.paging.impl.PagingStoreImpl;
@@ -55,7 +51,6 @@
 import org.hornetq.core.postoffice.PostOffice;
 import org.hornetq.core.server.HornetQServer;
 import org.hornetq.core.server.Queue;
-import org.hornetq.core.server.ServerMessage;
 import org.hornetq.core.server.impl.HornetQServerImpl;
 import org.hornetq.core.settings.impl.AddressFullMessagePolicy;
 import org.hornetq.core.settings.impl.AddressSettings;
@@ -118,6 +113,16 @@
 
    public void testWithDiverts() throws Exception
    {
+      internalMultiQueuesTest(true);
+   }
+   
+   public void testWithMultiQueues() throws Exception
+   {
+      internalMultiQueuesTest(false);
+   }
+   
+   public void internalMultiQueuesTest(final boolean divert) throws Exception
+   {
       clearData();
 
       Configuration config = createDefaultConfig();
@@ -128,28 +133,31 @@
                                           PagingTest.PAGE_MAX,
                                           new HashMap<String, AddressSettings>());
 
-      DivertConfiguration divert1 = new DivertConfiguration("dv1",
-                                                            "nm1",
-                                                            PagingTest.ADDRESS.toString(),
-                                                            PagingTest.ADDRESS.toString() + "-1",
-                                                            true,
-                                                            null,
-                                                            null);
+      if (divert)
+      {   
+         DivertConfiguration divert1 = new DivertConfiguration("dv1",
+                                                               "nm1",
+                                                               PagingTest.ADDRESS.toString(),
+                                                               PagingTest.ADDRESS.toString() + "-1",
+                                                               true,
+                                                               null,
+                                                               null);
+   
+         DivertConfiguration divert2 = new DivertConfiguration("dv2",
+                                                               "nm2",
+                                                               PagingTest.ADDRESS.toString(),
+                                                               PagingTest.ADDRESS.toString() + "-2",
+                                                               true,
+                                                               null,
+                                                               null);
+   
+         ArrayList<DivertConfiguration> divertList = new ArrayList<DivertConfiguration>();
+         divertList.add(divert1);
+         divertList.add(divert2);
+   
+         config.setDivertConfigurations(divertList);
+      }
 
-      DivertConfiguration divert2 = new DivertConfiguration("dv2",
-                                                            "nm2",
-                                                            PagingTest.ADDRESS.toString(),
-                                                            PagingTest.ADDRESS.toString() + "-2",
-                                                            true,
-                                                            null,
-                                                            null);
-
-      ArrayList<DivertConfiguration> divertList = new ArrayList<DivertConfiguration>();
-      divertList.add(divert1);
-      divertList.add(divert2);
-
-      config.setDivertConfigurations(divertList);
-
       server.start();
 
       final int messageSize = 1024;
@@ -176,10 +184,19 @@
 
             ClientSession session = sf.createSession(false, false, false);
 
-            session.createQueue(PagingTest.ADDRESS + "-1", PagingTest.ADDRESS + "-1", null, true);
+            if (divert)
+            {
+               session.createQueue(PagingTest.ADDRESS + "-1", PagingTest.ADDRESS + "-1", null, true);
 
-            session.createQueue(PagingTest.ADDRESS + "-2", PagingTest.ADDRESS + "-2", null, true);
+               session.createQueue(PagingTest.ADDRESS + "-2", PagingTest.ADDRESS + "-2", null, true);
+            }
+            else
+            {
+               session.createQueue(PagingTest.ADDRESS.toString(), PagingTest.ADDRESS + "-1", null, true);
 
+               session.createQueue(PagingTest.ADDRESS.toString(), PagingTest.ADDRESS + "-2", null, true);
+            }
+
             ClientProducer producer = session.createProducer(PagingTest.ADDRESS);
 
             ClientMessage message = null;
@@ -319,6 +336,8 @@
 
    private void internaltestSendReceivePaging(final boolean persistentMessages) throws Exception
    {
+      
+      System.out.println("PageDir:" + getPageDir());
       clearData();
 
       Configuration config = createDefaultConfig();
@@ -448,7 +467,7 @@
 
       UnitTestCase.assertEqualsByteArrays(body, other);
    }
-
+   
    /**
     * - Make a destination in page mode
     * - Add stuff to a transaction
@@ -903,7 +922,7 @@
                      msg.putIntProperty("count", i);
                      producer.send(msg);
 
-                     if (i % 50 == 0 && i != 0)
+                     if (i % 100 == 0 && i != 0)
                      {
                         sessionProducer.commit();
                         // Thread.sleep(500);
@@ -947,17 +966,17 @@
          ClientConsumer consumer = session.createConsumer(PagingTest.ADDRESS);
 
          for (int i = 0; i < numberOfMessages; i++)
-         {
-            ClientMessage msg = consumer.receive(500000);
+         {  
+            ClientMessage msg = consumer.receive(5000);
             assertNotNull(msg);
             assertEquals(i, msg.getIntProperty("count").intValue());
             msg.acknowledge();
             if (i > 0 && i % 10 == 0)
             {
-               // session.commit();
+              session.commit();
             }
          }
-         // session.commit();
+         session.commit();
 
          session.close();
 
@@ -979,7 +998,7 @@
    }
 
    // This test will force a depage thread as soon as the first message hits the page
-   public void testDepageOnTX5() throws Exception
+   public void testDepageDuringTransaction5() throws Exception
    {
       clearData();
 
@@ -999,7 +1018,7 @@
                          final PagingStoreFactory storeFactory,
                          final SimpleString storeName,
                          final AddressSettings addressSettings,
-                         final Executor executor,
+                         final ExecutorFactory executorFactory,
                          final boolean syncNonTransactional)
          {
             super(address,
@@ -1010,41 +1029,10 @@
                   storeFactory,
                   storeName,
                   addressSettings,
-                  executor,
+                  executorFactory,
                   syncNonTransactional);
          }
 
-         protected boolean page(final List<ServerMessage> messages, final long transactionID, final boolean sync) throws Exception
-         {
-            boolean paged = super.page(messages, transactionID, sync);
-
-            if (paged)
-            {
-
-               if (countDepage.incrementAndGet() == 1)
-               {
-                  countDepage.set(0);
-
-                  executor.execute(new Runnable()
-                  {
-                     public void run()
-                     {
-                        try
-                        {
-                           while (isStarted() && readPage());
-                        }
-                        catch (Exception e)
-                        {
-                           e.printStackTrace();
-                        }
-                     }
-                  });
-               }
-            }
-
-            return paged;
-         }
-
          public boolean startDepaging()
          {
             // do nothing, we are hacking depage right in between paging
@@ -1062,7 +1050,7 @@
             super(directory, executorFactory, syncNonTransactional);
          }
 
-         public synchronized PagingStore newStore(final SimpleString address, final AddressSettings settings) throws Exception
+         public synchronized PagingStore newStore(final SimpleString address, final AddressSettings settings)
          {
 
             return new HackPagingStore(address,
@@ -1073,7 +1061,7 @@
                                        this,
                                        address,
                                        settings,
-                                       getExecutorFactory().getExecutor(),
+                                       getExecutorFactory(),
                                        syncNonTransactional);
          }
 
@@ -1308,8 +1296,9 @@
 
          for (int i = 0; i < numberOfMessages; i++)
          {
-            ClientMessage msg = consumer.receive(500000);
+            ClientMessage msg = consumer.receive(5000);
             assertNotNull(msg);
+            System.out.println("Received " + i);
             assertEquals(i, msg.getIntProperty("count").intValue());
             msg.acknowledge();
          }

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/paging/PageCrashTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/paging/PageCrashTest.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/paging/PageCrashTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -18,7 +18,6 @@
 import java.lang.reflect.Field;
 import java.util.HashMap;
 import java.util.List;
-import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 
 import junit.framework.Assert;
@@ -34,6 +33,7 @@
 import org.hornetq.core.paging.PagedMessage;
 import org.hornetq.core.paging.PagingManager;
 import org.hornetq.core.paging.PagingStore;
+import org.hornetq.core.paging.cursor.LivePageCache;
 import org.hornetq.core.paging.impl.PagingManagerImpl;
 import org.hornetq.core.paging.impl.PagingStoreFactoryNIO;
 import org.hornetq.core.paging.impl.PagingStoreImpl;
@@ -43,6 +43,7 @@
 import org.hornetq.spi.core.security.HornetQSecurityManager;
 import org.hornetq.spi.core.security.HornetQSecurityManagerImpl;
 import org.hornetq.tests.util.ServiceTestBase;
+import org.hornetq.utils.ExecutorFactory;
 import org.hornetq.utils.OrderedExecutorFactory;
 
 /**
@@ -286,13 +287,21 @@
          // Public --------------------------------------------------------
 
          @Override
-         public synchronized PagingStore newStore(final SimpleString destinationName, final AddressSettings settings) throws Exception
+         public synchronized PagingStore newStore(final SimpleString destinationName, final AddressSettings settings)
          {
-            Field factoryField = PagingStoreFactoryNIO.class.getDeclaredField("executorFactory");
-            factoryField.setAccessible(true);
-
-            OrderedExecutorFactory factory = (org.hornetq.utils.OrderedExecutorFactory)factoryField.get(this);
-            return new FailingPagingStore(destinationName, settings, factory.getExecutor(), syncNonTransactional);
+            try
+            {
+               Field factoryField = PagingStoreFactoryNIO.class.getDeclaredField("executorFactory");
+               factoryField.setAccessible(true);
+   
+               OrderedExecutorFactory factory = (org.hornetq.utils.OrderedExecutorFactory)factoryField.get(this);
+               return new FailingPagingStore(destinationName, settings, factory, syncNonTransactional);
+            }
+            catch (Exception e)
+            {
+               e.printStackTrace();// >> junit report
+               return null;
+            }
          }
 
          // Package protected ---------------------------------------------
@@ -312,7 +321,7 @@
              */
             public FailingPagingStore(final SimpleString storeName,
                                       final AddressSettings addressSettings,
-                                      final Executor executor,
+                                      final ExecutorFactory executor,
                                       final boolean syncNonTransactional)
             {
                super(storeName,
@@ -433,6 +442,13 @@
          {
             delegatedPage = delegatePage;
          }
+
+         /* (non-Javadoc)
+          * @see org.hornetq.core.paging.Page#setLiveCache(org.hornetq.core.paging.cursor.LivePageCache)
+          */
+         public void setLiveCache(LivePageCache pageCache)
+         {
+         }
       }
 
    }

Added: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/paging/PageCursorTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/paging/PageCursorTest.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/paging/PageCursorTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,1330 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.integration.paging;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import junit.framework.Assert;
+
+import org.hornetq.api.core.HornetQBuffer;
+import org.hornetq.api.core.SimpleString;
+import org.hornetq.api.core.client.ClientSession;
+import org.hornetq.api.core.client.ClientSessionFactory;
+import org.hornetq.core.config.Configuration;
+import org.hornetq.core.filter.Filter;
+import org.hornetq.core.paging.PagedMessage;
+import org.hornetq.core.paging.cursor.PageCache;
+import org.hornetq.core.paging.cursor.PageCursorProvider;
+import org.hornetq.core.paging.cursor.PagePosition;
+import org.hornetq.core.paging.cursor.PageSubscription;
+import org.hornetq.core.paging.cursor.PagedReference;
+import org.hornetq.core.paging.cursor.impl.PageCursorProviderImpl;
+import org.hornetq.core.paging.cursor.impl.PagePositionImpl;
+import org.hornetq.core.paging.cursor.impl.PageSubscriptionImpl;
+import org.hornetq.core.paging.impl.PagingStoreImpl;
+import org.hornetq.core.persistence.StorageManager;
+import org.hornetq.core.persistence.impl.journal.OperationContextImpl;
+import org.hornetq.core.server.HornetQServer;
+import org.hornetq.core.server.Queue;
+import org.hornetq.core.server.RoutingContext;
+import org.hornetq.core.server.ServerMessage;
+import org.hornetq.core.server.impl.RoutingContextImpl;
+import org.hornetq.core.server.impl.ServerMessageImpl;
+import org.hornetq.core.settings.impl.AddressSettings;
+import org.hornetq.core.transaction.Transaction;
+import org.hornetq.core.transaction.impl.TransactionImpl;
+import org.hornetq.tests.unit.core.postoffice.impl.FakeQueue;
+import org.hornetq.tests.util.RandomUtil;
+import org.hornetq.tests.util.ServiceTestBase;
+import org.hornetq.utils.LinkedListIterator;
+
+/**
+ * A PageCursorTest
+ *
+ * @author <a href="mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class PageCursorTest extends ServiceTestBase
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   private SimpleString ADDRESS = new SimpleString("test-add");
+
+   private HornetQServer server;
+
+   private Queue queue;
+   
+   private List<Queue> queueList;
+
+   private static final int PAGE_MAX = -1;
+
+   private static final int PAGE_SIZE = 10 * 1024 * 1024;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   // Read more cache than what would fit on the memory, and validate if the memory would be cleared through soft-caches
+   public void testReadCache() throws Exception
+   {
+
+      final int NUM_MESSAGES = 1000;
+
+      int numberOfPages = addMessages(NUM_MESSAGES, 1024 * 1024);
+
+      System.out.println("NumberOfPages = " + numberOfPages);
+
+      PageCursorProviderImpl cursorProvider = new PageCursorProviderImpl(lookupPageStore(ADDRESS),
+                                                                         server.getStorageManager(),
+                                                                         server.getExecutorFactory());
+
+      for (int i = 0; i < numberOfPages; i++)
+      {
+         PageCache cache = cursorProvider.getPageCache(new PagePositionImpl(i + 1, 0));
+         System.out.println("Page " + i + " had " + cache.getNumberOfMessages() + " messages");
+
+      }
+
+      forceGC();
+
+      assertTrue(cursorProvider.getCacheSize() < numberOfPages);
+
+      System.out.println("Cache size = " + cursorProvider.getCacheSize());
+   }
+
+   public void testSimpleCursor() throws Exception
+   {
+
+      final int NUM_MESSAGES = 100;
+
+      PageSubscription cursor = lookupPageStore(ADDRESS).getCursorProvier().getSubscription(queue.getID());
+      
+      Iterator<PagedReference> iterEmpty = cursor.iterator();
+
+      int numberOfPages = addMessages(NUM_MESSAGES, 1024 * 1024);
+
+      System.out.println("NumberOfPages = " + numberOfPages);
+
+      PagedReference msg;
+
+      LinkedListIterator<PagedReference> iterator = cursor.iterator();
+      int key = 0;
+      while ((msg = iterator.next()) != null)
+      {
+         assertEquals(key++, msg.getMessage().getIntProperty("key").intValue());
+         cursor.ack(msg.getPosition());
+      }
+      assertEquals(NUM_MESSAGES, key);
+
+      server.getStorageManager().waitOnOperations();
+
+      waitCleanup();
+
+      assertFalse(lookupPageStore(ADDRESS).isPaging());
+
+      assertEquals(1, lookupPageStore(ADDRESS).getNumberOfPages());
+
+      forceGC();
+
+      server.stop();
+      createServer();
+      waitCleanup();
+      assertEquals(1, lookupPageStore(ADDRESS).getNumberOfPages());
+
+   }
+
+   public void testSimpleCursorWithFilter() throws Exception
+   {
+
+      final int NUM_MESSAGES = 100;
+
+      PageSubscription cursorEven = createNonPersistentCursor(new Filter()
+      {
+
+         public boolean match(ServerMessage message)
+         {
+            Boolean property = message.getBooleanProperty("even");
+            if (property == null)
+            {
+               return false;
+            }
+            else
+            {
+               return property.booleanValue();
+            }
+         }
+
+         public SimpleString getFilterString()
+         {
+            return new SimpleString("even=true");
+         }
+
+      });
+
+      PageSubscription cursorOdd = createNonPersistentCursor(new Filter()
+      {
+
+         public boolean match(ServerMessage message)
+         {
+            Boolean property = message.getBooleanProperty("even");
+            if (property == null)
+            {
+               return false;
+            }
+            else
+            {
+               return !property.booleanValue();
+            }
+         }
+
+         public SimpleString getFilterString()
+         {
+            return new SimpleString("even=true");
+         }
+
+      });
+
+      int numberOfPages = addMessages(NUM_MESSAGES, 1024 * 1024);
+
+      System.out.println("NumberOfPages = " + numberOfPages);
+
+      queue.getPageSubscription().close();
+
+      PagedReference msg;
+
+      LinkedListIterator<PagedReference> iteratorEven = cursorEven.iterator();
+
+      LinkedListIterator<PagedReference> iteratorOdd = cursorOdd.iterator();
+
+      int key = 0;
+      while ((msg = iteratorEven.next()) != null)
+      {
+         System.out.println("Received" + msg);
+         assertEquals(key, msg.getMessage().getIntProperty("key").intValue());
+         assertTrue(msg.getMessage().getBooleanProperty("even").booleanValue());
+         key += 2;
+         cursorEven.ack(msg.getPosition());
+      }
+      assertEquals(NUM_MESSAGES, key);
+
+      key = 1;
+      while ((msg = iteratorOdd.next()) != null)
+      {
+         assertEquals(key, msg.getMessage().getIntProperty("key").intValue());
+         assertFalse(msg.getMessage().getBooleanProperty("even").booleanValue());
+         key += 2;
+         cursorOdd.ack(msg.getPosition());
+      }
+      assertEquals(NUM_MESSAGES + 1, key);
+
+      forceGC();
+
+      // assertTrue(lookupCursorProvider().getCacheSize() < numberOfPages);
+
+      server.stop();
+      createServer();
+      waitCleanup();
+      assertEquals(1, lookupPageStore(ADDRESS).getNumberOfPages());
+
+   }
+
+   public void testReadNextPage() throws Exception
+   {
+
+      final int NUM_MESSAGES = 1;
+
+      int numberOfPages = addMessages(NUM_MESSAGES, 1024);
+
+      System.out.println("NumberOfPages = " + numberOfPages);
+
+      PageCursorProvider cursorProvider = lookupCursorProvider();
+
+      PageCache cache = cursorProvider.getPageCache(new PagePositionImpl(2, 0));
+
+      assertNull(cache);
+   }
+
+   public void testRestart() throws Exception
+   {
+      final int NUM_MESSAGES = 1000;
+
+      int numberOfPages = addMessages(NUM_MESSAGES, 100 * 1024);
+
+      System.out.println("Number of pages = " + numberOfPages);
+
+      PageCursorProvider cursorProvider = lookupCursorProvider();
+
+      PageSubscription cursor = this.server.getPagingManager()
+                                           .getPageStore(ADDRESS)
+                                           .getCursorProvier()
+                                           .getSubscription(queue.getID());
+
+      PageCache firstPage = cursorProvider.getPageCache(new PagePositionImpl(server.getPagingManager()
+                                                                                   .getPageStore(ADDRESS)
+                                                                                   .getFirstPage(), 0));
+
+      int firstPageSize = firstPage.getNumberOfMessages();
+
+      firstPage = null;
+
+      System.out.println("Cursor: " + cursor);
+      cursorProvider.printDebug();
+
+      LinkedListIterator<PagedReference> iterator = cursor.iterator();
+
+      for (int i = 0; i < 1000; i++)
+      {
+         System.out.println("Reading Msg : " + i);
+         PagedReference msg = iterator.next();
+         assertNotNull(msg);
+         assertEquals(i, msg.getMessage().getIntProperty("key").intValue());
+
+         if (i < firstPageSize)
+         {
+            cursor.ack(msg);
+         }
+      }
+      cursorProvider.printDebug();
+
+      server.getStorageManager().waitOnOperations();
+      lookupPageStore(ADDRESS).flushExecutors();
+
+      // needs to clear the context since we are using the same thread over two distinct servers
+      // otherwise we will get the old executor on the factory
+      OperationContextImpl.clearContext();
+
+      server.stop();
+
+      server.start();
+
+      cursor = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvier().getSubscription(queue.getID());
+
+      iterator = cursor.iterator();
+
+      for (int i = firstPageSize; i < NUM_MESSAGES; i++)
+      {
+         System.out.println("Received " + i);
+         PagedReference msg = iterator.next();
+         assertNotNull(msg);
+         assertEquals(i, msg.getMessage().getIntProperty("key").intValue());
+
+         cursor.ack(msg);
+
+         OperationContextImpl.getContext(null).waitCompletion();
+
+      }
+
+      OperationContextImpl.getContext(null).waitCompletion();
+
+      lookupPageStore(ADDRESS).flushExecutors();
+
+      assertFalse(lookupPageStore(ADDRESS).isPaging());
+
+      server.stop();
+      createServer();
+      assertFalse(lookupPageStore(ADDRESS).isPaging());
+      waitCleanup();
+      assertEquals(1, lookupPageStore(ADDRESS).getNumberOfPages());
+
+   }
+
+   public void testRestartWithHoleOnAck() throws Exception
+   {
+
+      final int NUM_MESSAGES = 1000;
+
+      int numberOfPages = addMessages(NUM_MESSAGES, 10 * 1024);
+
+      System.out.println("Number of pages = " + numberOfPages);
+
+      PageCursorProvider cursorProvider = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvier();
+      System.out.println("cursorProvider = " + cursorProvider);
+
+      PageSubscription cursor = this.server.getPagingManager()
+                                           .getPageStore(ADDRESS)
+                                           .getCursorProvier()
+                                           .getSubscription(queue.getID());
+
+      System.out.println("Cursor: " + cursor);
+      LinkedListIterator<PagedReference> iterator = cursor.iterator();
+      for (int i = 0; i < 100; i++)
+      {
+         PagedReference msg = iterator.next();
+         assertEquals(i, msg.getMessage().getIntProperty("key").intValue());
+         if (i < 10 || i > 20)
+         {
+            cursor.ack(msg);
+         }
+      }
+      
+      server.getStorageManager().waitOnOperations();
+
+      server.stop();
+
+      OperationContextImpl.clearContext();
+
+      server.start();
+
+      cursor = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvier().getSubscription(queue.getID());
+      iterator = cursor.iterator();
+
+      for (int i = 10; i <= 20; i++)
+      {
+         PagedReference msg = iterator.next();
+         assertEquals(i, msg.getMessage().getIntProperty("key").intValue());
+         cursor.ack(msg);
+      }
+
+      for (int i = 100; i < NUM_MESSAGES; i++)
+      {
+         PagedReference msg = iterator.next();
+         assertEquals(i, msg.getMessage().getIntProperty("key").intValue());
+         cursor.ack(msg);
+      }
+
+      server.stop();
+      createServer();
+      waitCleanup();
+      assertEquals(1, lookupPageStore(ADDRESS).getNumberOfPages());
+
+   }
+
+   public void testRestartWithHoleOnAckAndTransaction() throws Exception
+   {
+      final int NUM_MESSAGES = 1000;
+
+      int numberOfPages = addMessages(NUM_MESSAGES, 10 * 1024);
+
+      System.out.println("Number of pages = " + numberOfPages);
+
+      PageCursorProvider cursorProvider = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvier();
+      System.out.println("cursorProvider = " + cursorProvider);
+
+      PageSubscription cursor = this.server.getPagingManager()
+                                           .getPageStore(ADDRESS)
+                                           .getCursorProvier()
+                                           .getSubscription(queue.getID());
+
+      System.out.println("Cursor: " + cursor);
+
+      Transaction tx = new TransactionImpl(server.getStorageManager(), 60 * 1000);
+
+      LinkedListIterator<PagedReference> iterator = cursor.iterator();
+
+      for (int i = 0; i < 100; i++)
+      {
+         PagedReference msg = iterator.next();
+         assertEquals(i, msg.getMessage().getIntProperty("key").intValue());
+         if (i < 10 || i > 20)
+         {
+            cursor.ackTx(tx, msg);
+         }
+      }
+
+      tx.commit();
+
+      server.stop();
+
+      OperationContextImpl.clearContext();
+
+      server.start();
+
+      cursor = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvier().getSubscription(queue.getID());
+
+      tx = new TransactionImpl(server.getStorageManager(), 60 * 1000);
+      iterator = cursor.iterator();
+
+      for (int i = 10; i <= 20; i++)
+      {
+         PagedReference msg = iterator.next();
+         assertEquals(i, msg.getMessage().getIntProperty("key").intValue());
+         cursor.ackTx(tx, msg);
+      }
+
+      for (int i = 100; i < NUM_MESSAGES; i++)
+      {
+         PagedReference msg = iterator.next();
+         assertEquals(i, msg.getMessage().getIntProperty("key").intValue());
+         cursor.ackTx(tx, msg);
+      }
+
+      tx.commit();
+
+      server.stop();
+      createServer();
+      waitCleanup();
+      assertEquals(1, lookupPageStore(ADDRESS).getNumberOfPages());
+
+   }
+
+   public void testConsumeLivePage() throws Exception
+   {
+      PagingStoreImpl pageStore = lookupPageStore(ADDRESS);
+
+      pageStore.startPaging();
+
+      final int NUM_MESSAGES = 100;
+
+      final int messageSize = 1024 * 1024;
+
+      PageCursorProvider cursorProvider = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvier();
+      System.out.println("cursorProvider = " + cursorProvider);
+
+      PageSubscription cursor = this.server.getPagingManager()
+                                           .getPageStore(ADDRESS)
+                                           .getCursorProvier()
+                                           .getSubscription(queue.getID());
+
+      System.out.println("Cursor: " + cursor);
+      
+      RoutingContextImpl ctx = generateCTX();
+
+      LinkedListIterator<PagedReference> iterator = cursor.iterator();
+
+      for (int i = 0; i < NUM_MESSAGES; i++)
+      {
+         // if (i % 100 == 0)
+         System.out.println("read/written " + i);
+
+         HornetQBuffer buffer = RandomUtil.randomBuffer(messageSize, i + 1l);
+
+         ServerMessage msg = new ServerMessageImpl(i, buffer.writerIndex());
+         msg.putIntProperty("key", i);
+
+         msg.getBodyBuffer().writeBytes(buffer, 0, buffer.writerIndex());
+
+         Assert.assertTrue(pageStore.page(msg, ctx, ctx.getContextListing(ADDRESS)));
+
+         PagedReference readMessage = iterator.next();
+
+         assertNotNull(readMessage);
+
+         assertEquals(i, readMessage.getMessage().getIntProperty("key").intValue());
+
+         assertNull(iterator.next());
+      }
+
+      server.stop();
+
+      OperationContextImpl.clearContext();
+
+      createServer();
+
+      pageStore = lookupPageStore(ADDRESS);
+
+      cursor = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvier().getSubscription(queue.getID());
+      iterator = cursor.iterator();
+
+      for (int i = 0; i < NUM_MESSAGES * 2; i++)
+      {
+         if (i % 100 == 0)
+            System.out.println("Paged " + i);
+
+         if (i >= NUM_MESSAGES)
+         {
+
+            HornetQBuffer buffer = RandomUtil.randomBuffer(messageSize, i + 1l);
+
+            ServerMessage msg = new ServerMessageImpl(i, buffer.writerIndex());
+            msg.putIntProperty("key", i);
+
+            msg.getBodyBuffer().writeBytes(buffer, 0, buffer.writerIndex());
+
+            Assert.assertTrue(pageStore.page(msg, ctx, ctx.getContextListing(ADDRESS)));
+         }
+
+         PagedReference readMessage = iterator.next();
+
+         assertNotNull(readMessage);
+
+         assertEquals(i, readMessage.getMessage().getIntProperty("key").intValue());
+      }
+
+      server.stop();
+
+      OperationContextImpl.clearContext();
+
+      createServer();
+
+      pageStore = lookupPageStore(ADDRESS);
+
+      cursor = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvier().getSubscription(queue.getID());
+      iterator = cursor.iterator();
+
+      for (int i = 0; i < NUM_MESSAGES * 3; i++)
+      {
+         if (i % 100 == 0)
+            System.out.println("Paged " + i);
+
+         if (i >= NUM_MESSAGES * 2 - 1)
+         {
+
+            HornetQBuffer buffer = RandomUtil.randomBuffer(messageSize, i + 1l);
+
+            ServerMessage msg = new ServerMessageImpl(i, buffer.writerIndex());
+            msg.putIntProperty("key", i + 1);
+
+            msg.getBodyBuffer().writeBytes(buffer, 0, buffer.writerIndex());
+
+            Assert.assertTrue(pageStore.page(msg, ctx, ctx.getContextListing(ADDRESS)));
+         }
+
+         PagedReference readMessage = iterator.next();
+
+         assertNotNull(readMessage);
+
+         cursor.ack(readMessage);
+
+         assertEquals(i, readMessage.getMessage().getIntProperty("key").intValue());
+      }
+
+      PagedReference readMessage = iterator.next();
+
+      assertEquals(NUM_MESSAGES * 3, readMessage.getMessage().getIntProperty("key").intValue());
+
+      cursor.ack(readMessage);
+
+      server.getStorageManager().waitOnOperations();
+
+      pageStore.flushExecutors();
+
+      assertFalse(pageStore.isPaging());
+
+      server.stop();
+      createServer();
+
+      assertFalse(pageStore.isPaging());
+
+      waitCleanup();
+
+      assertFalse(lookupPageStore(ADDRESS).isPaging());
+
+   }
+   
+
+   public void testConsumeLivePageMultiThread() throws Exception
+   {
+      final PagingStoreImpl pageStore = lookupPageStore(ADDRESS);
+
+      pageStore.startPaging();
+
+      final int NUM_TX = 100;
+      
+      final int MSGS_TX = 100;
+      
+      final int TOTAL_MSG = NUM_TX * MSGS_TX;
+
+      final int messageSize = 1024;
+
+      PageCursorProvider cursorProvider = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvier();
+      System.out.println("cursorProvider = " + cursorProvider);
+
+      PageSubscription cursor = this.server.getPagingManager()
+                                           .getPageStore(ADDRESS)
+                                           .getCursorProvier()
+                                           .getSubscription(queue.getID());
+
+      System.out.println("Cursor: " + cursor);
+      
+      final StorageManager storage = this.server.getStorageManager();
+      
+      final AtomicInteger exceptions = new AtomicInteger(0);
+      
+      Thread t1 = new Thread()
+      {
+         public void run()
+         {
+            try
+            {
+               int count = 0;
+               
+               for (int txCount = 0; txCount < NUM_TX; txCount++)
+               {
+                  
+                  Transaction tx = null;
+                  
+                  if (txCount % 2 == 0)
+                  {
+                     tx = new TransactionImpl(storage);
+                  }
+
+                  RoutingContext ctx = generateCTX(tx);
+                  
+                  for (int i = 0 ; i < MSGS_TX; i++)
+                  {
+                     //System.out.println("Sending " + count);
+                     HornetQBuffer buffer = RandomUtil.randomBuffer(messageSize, count);
+
+                     ServerMessage msg = new ServerMessageImpl(i, buffer.writerIndex());
+                     msg.putIntProperty("key", count++);
+
+                     msg.getBodyBuffer().writeBytes(buffer, 0, buffer.writerIndex());
+
+                     Assert.assertTrue(pageStore.page(msg, ctx, ctx.getContextListing(ADDRESS)));
+                  }
+                  
+                  if (tx != null)
+                  {
+                     tx.commit();
+                  }
+                  
+               }
+            }
+            catch (Throwable e)
+            {
+               e.printStackTrace();
+               exceptions.incrementAndGet();
+            }
+         }
+      };
+      
+      t1.start();
+      
+      
+      LinkedListIterator<PagedReference> iterator = cursor.iterator();
+      
+      for (int i = 0 ; i < TOTAL_MSG; i++ )
+      {
+         assertEquals(0, exceptions.get());
+         PagedReference ref = null;
+         for (int repeat = 0 ; repeat < 5; repeat++)
+         {
+            ref = iterator.next();
+            if (ref == null)
+            {
+               Thread.sleep(1000);
+            }
+            else
+            {
+               break;
+            }
+         }
+         assertNotNull(ref);
+         
+         ref.acknowledge();
+         assertNotNull(ref);
+         
+         System.out.println("Consuming " + ref.getMessage().getIntProperty("key"));
+         //assertEquals(i, ref.getMessage().getIntProperty("key").intValue());
+      }
+
+      assertEquals(0, exceptions.get());
+   }
+   
+   private RoutingContextImpl generateCTX()
+   {
+      return generateCTX(null);
+   }
+   
+   private RoutingContextImpl generateCTX(Transaction tx)
+   {
+      RoutingContextImpl ctx = new RoutingContextImpl(tx);
+      ctx.addQueue(ADDRESS, queue);
+      
+      for (Queue q : this.queueList)
+      {
+         ctx.addQueue(ADDRESS, q);
+      }
+      
+      return ctx;
+   }
+
+   /**
+    * @throws Exception
+    * @throws InterruptedException
+    */
+   private void waitCleanup() throws Exception, InterruptedException
+   {
+      // The cleanup is done asynchronously, so we need to wait some time
+      long timeout = System.currentTimeMillis() + 10000;
+
+      while (System.currentTimeMillis() < timeout && lookupPageStore(ADDRESS).getNumberOfPages() != 1)
+      {
+         Thread.sleep(100);
+      }
+
+      assertTrue("expected " + lookupPageStore(ADDRESS).getNumberOfPages(),
+                 lookupPageStore(ADDRESS).getNumberOfPages() <= 2);
+   }
+
+   public void testPrepareScenarios() throws Exception
+   {
+      PagingStoreImpl pageStore = lookupPageStore(ADDRESS);
+
+      pageStore.startPaging();
+
+      final int NUM_MESSAGES = 100;
+
+      final int messageSize = 100 * 1024;
+
+      PageCursorProvider cursorProvider = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvier();
+      System.out.println("cursorProvider = " + cursorProvider);
+
+      PageSubscription cursor = this.server.getPagingManager()
+                                           .getPageStore(ADDRESS)
+                                           .getCursorProvier()
+                                           .getSubscription(queue.getID());
+      LinkedListIterator<PagedReference> iterator = cursor.iterator();
+
+      System.out.println("Cursor: " + cursor);
+
+      StorageManager storage = this.server.getStorageManager();
+
+      long pgtxRollback = storage.generateUniqueID();
+      long pgtxForgotten = storage.generateUniqueID();
+      long pgtxCommit = storage.generateUniqueID();
+
+      Transaction txRollback = pgMessages(storage, pageStore, pgtxRollback, 0, NUM_MESSAGES, messageSize);
+      pageStore.forceAnotherPage();
+      Transaction txForgotten = pgMessages(storage, pageStore, pgtxForgotten, 100, NUM_MESSAGES, messageSize);
+      pageStore.forceAnotherPage();
+      Transaction txCommit = pgMessages(storage, pageStore, pgtxCommit, 200, NUM_MESSAGES, messageSize);
+      pageStore.forceAnotherPage();
+
+      addMessages(300, NUM_MESSAGES, messageSize);
+
+      System.out.println("Number of pages - " + pageStore.getNumberOfPages());
+
+      // First consume what's already there without any tx as nothing was committed
+      for (int i = 300; i < 400; i++)
+      {
+         PagedReference pos = iterator.next();
+         assertNotNull("Null at position " + i, pos);
+         assertEquals(i, pos.getMessage().getIntProperty("key").intValue());
+         cursor.ack(pos);
+      }
+
+      assertNull(iterator.next());
+
+      cursor.printDebug();
+ 
+      txCommit.commit();
+
+      txRollback.rollback();
+      
+      storage.waitOnOperations();
+
+      // Second:after pgtxCommit was done
+      for (int i = 200; i < 300; i++)
+      {
+         PagedReference pos = iterator.next();
+         assertNotNull(pos);
+         assertEquals(i, pos.getMessage().getIntProperty("key").intValue());
+         cursor.ack(pos);
+      }
+
+      assertNull(iterator.next());
+      
+      server.getStorageManager().waitOnOperations();
+
+      server.stop();
+      createServer();
+
+      long timeout = System.currentTimeMillis() + 10000;
+
+      while (System.currentTimeMillis() < timeout && lookupPageStore(ADDRESS).getNumberOfPages() != 1)
+      {
+         Thread.sleep(500);
+      }
+      assertEquals(1, lookupPageStore(ADDRESS).getNumberOfPages());
+
+   }
+
+
+   public void testLazyCommit() throws Exception
+   {
+      PagingStoreImpl pageStore = lookupPageStore(ADDRESS);
+
+      pageStore.startPaging();
+
+      final int NUM_MESSAGES = 100;
+
+      final int messageSize = 100 * 1024;
+
+      PageCursorProvider cursorProvider = this.server.getPagingManager().getPageStore(ADDRESS).getCursorProvier();
+      System.out.println("cursorProvider = " + cursorProvider);
+
+      PageSubscription cursor = this.server.getPagingManager()
+                                           .getPageStore(ADDRESS)
+                                           .getCursorProvier()
+                                           .getSubscription(queue.getID());
+      LinkedListIterator<PagedReference> iterator = cursor.iterator();
+
+      System.out.println("Cursor: " + cursor);
+
+      StorageManager storage = this.server.getStorageManager();
+
+      long pgtxLazy = storage.generateUniqueID();
+
+      Transaction txLazy = pgMessages(storage, pageStore, pgtxLazy, 0, NUM_MESSAGES, messageSize);
+
+      addMessages(100, NUM_MESSAGES, messageSize);
+
+      System.out.println("Number of pages - " + pageStore.getNumberOfPages());
+
+      // First consume what's already there without any tx as nothing was committed
+      for (int i = 100; i < 200; i++)
+      {
+         PagedReference pos = iterator.next();
+         assertNotNull("Null at position " + i, pos);
+         assertEquals(i, pos.getMessage().getIntProperty("key").intValue());
+         cursor.ack(pos);
+      }
+
+      assertNull(iterator.next());
+      
+      txLazy.commit();
+      
+      storage.waitOnOperations();
+
+      for (int i = 0; i < 100; i++)
+      {
+         PagedReference pos = iterator.next();
+         assertNotNull("Null at position " + i, pos);
+         assertEquals(i, pos.getMessage().getIntProperty("key").intValue());
+         cursor.ack(pos);
+      }
+
+      assertNull(iterator.next());
+
+      waitCleanup();
+
+      server.stop();
+      createServer();
+      waitCleanup();
+      assertEquals(1, lookupPageStore(ADDRESS).getNumberOfPages());
+
+   }
+
+   public void testCloseNonPersistentConsumer() throws Exception
+   {
+
+      final int NUM_MESSAGES = 100;
+
+      PageCursorProvider cursorProvider = lookupCursorProvider();
+
+      PageSubscription cursor = cursorProvider.createSubscription(11, null, false);
+      PageSubscriptionImpl cursor2 = (PageSubscriptionImpl)cursorProvider.createSubscription(12, null, false);
+      
+      this.queueList.add(new FakeQueue(new SimpleString("a"), 11));
+      
+      this.queueList.add(new FakeQueue(new SimpleString("b"), 12));
+
+      int numberOfPages = addMessages(NUM_MESSAGES, 1024 * 1024);
+
+      System.out.println("NumberOfPages = " + numberOfPages);
+
+      queue.getPageSubscription().close();
+
+      PagedReference msg;
+      LinkedListIterator<PagedReference> iterator = cursor.iterator();
+      LinkedListIterator<PagedReference> iterator2 = cursor2.iterator();
+      
+      cursor2.bookmark(new PagePositionImpl(1, -1));
+
+      int key = 0;
+      while ((msg = iterator.next()) != null)
+      {
+         System.out.println("key = " + key);
+         assertEquals(key++, msg.getMessage().getIntProperty("key").intValue());
+         cursor.ack(msg);
+      }
+      assertEquals(NUM_MESSAGES, key);
+
+      forceGC();
+
+      for (int i = 0; i < 10; i++)
+      {
+         assertTrue(iterator2.hasNext());
+         msg = iterator2.next();
+         assertEquals(i, msg.getMessage().getIntProperty("key").intValue());
+      }
+
+      assertSame(cursor2.getProvider(), cursorProvider);
+
+      cursor2.close();
+
+      lookupPageStore(ADDRESS).flushExecutors();
+
+      server.stop();
+      createServer();
+      waitCleanup();
+      assertEquals(1, lookupPageStore(ADDRESS).getNumberOfPages());
+
+   }
+
+   public void testNoCursors() throws Exception
+   {
+
+      final int NUM_MESSAGES = 100;
+
+      int numberOfPages = addMessages(NUM_MESSAGES, 1024 * 1024);
+
+      ClientSessionFactory sf = createInVMFactory();
+      ClientSession session = sf.createSession();
+      session.deleteQueue(ADDRESS);
+
+      System.out.println("NumberOfPages = " + numberOfPages);
+
+      server.stop();
+      createServer();
+      waitCleanup();
+      assertEquals(0, lookupPageStore(ADDRESS).getNumberOfPages());
+
+   }
+
+   public void testFirstMessageInTheMiddle() throws Exception
+   {
+
+      final int NUM_MESSAGES = 100;
+
+      PageCursorProvider cursorProvider = lookupCursorProvider();
+
+      PageSubscription cursor = cursorProvider.createSubscription(2, null, false);
+      
+      queueList.add(new FakeQueue(new SimpleString("tmp"), 2));
+
+      int numberOfPages = addMessages(NUM_MESSAGES, 1024 * 1024);
+
+      System.out.println("NumberOfPages = " + numberOfPages);
+
+      PageCache cache = cursorProvider.getPageCache(new PagePositionImpl(5, 0));
+
+      queue.getPageSubscription().close();
+
+      PagePosition startingPos = new PagePositionImpl(5, cache.getNumberOfMessages() / 2);
+      cursor.bookmark(startingPos);
+      PagedMessage msg = cache.getMessage(startingPos.getMessageNr() + 1);
+      msg.initMessage(server.getStorageManager());
+      int key = msg.getMessage().getIntProperty("key").intValue();
+
+      msg = null;
+
+      cache = null;
+      LinkedListIterator<PagedReference> iterator = cursor.iterator();
+
+      PagedReference msgCursor = null;
+      while ((msgCursor = iterator.next()) != null)
+      {
+         assertEquals(key++, msgCursor.getMessage().getIntProperty("key").intValue());
+         cursor.ack(msgCursor);
+      }
+      assertEquals(NUM_MESSAGES, key);
+
+      forceGC();
+
+      // assertTrue(cursorProvider.getCacheSize() < numberOfPages);
+
+      server.stop();
+      createServer();
+      waitCleanup();
+      assertEquals(1, lookupPageStore(ADDRESS).getNumberOfPages());
+   }
+
+   public void testFirstMessageInTheMiddlePersistent() throws Exception
+   {
+
+      final int NUM_MESSAGES = 100;
+
+      int numberOfPages = addMessages(NUM_MESSAGES, 1024 * 1024);
+
+      System.out.println("NumberOfPages = " + numberOfPages);
+
+      PageCursorProvider cursorProvider = lookupCursorProvider();
+
+      PageCache cache = cursorProvider.getPageCache(new PagePositionImpl(5, 0));
+
+      PageSubscription cursor = cursorProvider.getSubscription(queue.getID());
+      PagePosition startingPos = new PagePositionImpl(5, cache.getNumberOfMessages() / 2);
+      cursor.bookmark(startingPos);
+
+      // We can't proceed until the operation has finished
+      server.getStorageManager().waitOnOperations();
+      
+      PagedMessage msg = cache.getMessage(startingPos.getMessageNr() + 1);
+      msg.initMessage(server.getStorageManager());
+      int initialKey = msg.getMessage().getIntProperty("key").intValue();
+      int key = initialKey;
+
+      msg = null;
+
+      cache = null;
+
+      LinkedListIterator<PagedReference> iterator = cursor.iterator();
+
+      PagedReference msgCursor = null;
+      while ((msgCursor = iterator.next()) != null)
+      {
+         assertEquals(key++, msgCursor.getMessage().getIntProperty("key").intValue());
+      }
+      assertEquals(NUM_MESSAGES, key);
+
+      server.stop();
+
+      OperationContextImpl.clearContext();
+
+      createServer();
+
+      cursorProvider = lookupCursorProvider();
+      cursor = cursorProvider.getSubscription(queue.getID());
+      key = initialKey;
+      iterator = cursor.iterator();
+      while ((msgCursor = iterator.next()) != null)
+      {
+         assertEquals(key++, msgCursor.getMessage().getIntProperty("key").intValue());
+         cursor.ack(msgCursor);
+      }
+
+      forceGC();
+
+      assertTrue(cursorProvider.getCacheSize() < numberOfPages);
+
+      server.stop();
+      createServer();
+      waitCleanup();
+      assertEquals(1, lookupPageStore(ADDRESS).getNumberOfPages());
+
+   }
+   
+   private int tstProperty(ServerMessage msg)
+   {
+      return msg.getIntProperty("key").intValue();
+   }
+
+   public void testMultipleIterators() throws Exception
+   {
+
+      final int NUM_MESSAGES = 10;
+
+      int numberOfPages = addMessages(NUM_MESSAGES, 1024 * 1024);
+
+      System.out.println("NumberOfPages = " + numberOfPages);
+
+      PageCursorProvider cursorProvider = lookupCursorProvider();
+
+      PageSubscription cursor = cursorProvider.getSubscription(queue.getID());
+
+      LinkedListIterator<PagedReference> iter = cursor.iterator();
+      
+      LinkedListIterator<PagedReference> iter2 = cursor.iterator();
+      
+      assertTrue(iter.hasNext());
+      
+      PagedReference msg1 = iter.next();
+      
+      PagedReference msg2 = iter2.next();
+      
+      assertEquals(tstProperty(msg1.getMessage()), tstProperty(msg2.getMessage()));
+      
+      System.out.println("property = " + tstProperty(msg1.getMessage()));
+
+      msg1 = iter.next();
+      
+      assertEquals(1, tstProperty(msg1.getMessage()));
+      
+      iter.remove();
+      
+      msg2 = iter2.next();
+      
+      assertEquals(2, tstProperty(msg2.getMessage()));
+      
+      iter2.repeat();
+      
+      msg2 = iter2.next();
+      
+      assertEquals(2, tstProperty(msg2.getMessage()));
+      
+      iter2.repeat();
+      
+      assertEquals(2, tstProperty(msg2.getMessage()));
+      
+      msg1 = iter.next();
+      
+      assertEquals(2, tstProperty(msg1.getMessage()));
+      
+      iter.repeat();
+      
+      msg1 = iter.next();
+      
+      assertEquals(2, tstProperty(msg1.getMessage()));
+      
+      assertTrue(iter2.hasNext());
+      
+      
+   }
+
+   private int addMessages(final int numMessages, final int messageSize) throws Exception
+   {
+      return addMessages(0, numMessages, messageSize);
+   }
+
+   /**
+    * @param numMessages
+    * @param pageStore
+    * @throws Exception
+    */
+   private int addMessages(final int start, final int numMessages, final int messageSize) throws Exception
+   {
+      PagingStoreImpl pageStore = lookupPageStore(ADDRESS);
+
+      pageStore.startPaging();
+      
+      RoutingContext ctx = generateCTX();
+
+      for (int i = start; i < start + numMessages; i++)
+      {
+         if (i % 100 == 0)
+            System.out.println("Paged " + i);
+         HornetQBuffer buffer = RandomUtil.randomBuffer(messageSize, i + 1l);
+
+         ServerMessage msg = new ServerMessageImpl(i, buffer.writerIndex());
+         msg.putIntProperty("key", i);
+         // to be used on tests that are validating filters
+         msg.putBooleanProperty("even", i % 2 == 0);
+
+         msg.getBodyBuffer().writeBytes(buffer, 0, buffer.writerIndex());
+
+         Assert.assertTrue(pageStore.page(msg, ctx, ctx.getContextListing(ADDRESS)));
+      }
+
+      return pageStore.getNumberOfPages();
+   }
+
+   /**
+    * @return
+    * @throws Exception
+    */
+   private PagingStoreImpl lookupPageStore(SimpleString address) throws Exception
+   {
+      return (PagingStoreImpl)server.getPagingManager().getPageStore(address);
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   protected void tearDown() throws Exception
+   {
+      server.stop();
+      server = null;
+      queue = null;
+      queueList = null;
+      super.tearDown();
+   }
+
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      OperationContextImpl.clearContext();
+      System.out.println("Tmp:" + getTemporaryDir());
+
+      queueList = new ArrayList<Queue>();
+      
+      createServer();
+   }
+
+   /**
+    * @throws Exception
+    */
+   private void createServer() throws Exception
+   {
+      OperationContextImpl.clearContext();
+
+      Configuration config = createDefaultConfig();
+
+      config.setJournalSyncNonTransactional(true);
+
+      server = createServer(true, config, PAGE_SIZE, PAGE_MAX, new HashMap<String, AddressSettings>());
+
+      server.start();
+
+      try
+      {
+         queue = server.createQueue(ADDRESS, ADDRESS, null, true, false);
+         queue.pause();
+      }
+      catch (Exception ignored)
+      {
+      }
+   }
+
+   /**
+    * @return
+    * @throws Exception
+    */
+   private PageSubscription createNonPersistentCursor(Filter filter) throws Exception
+   {
+      long id = server.getStorageManager().generateUniqueID();
+      queueList.add(new FakeQueue(new SimpleString(filter.toString()), id));
+      return lookupCursorProvider().createSubscription(id, filter, false);
+   }
+
+   /**
+    * @return
+    * @throws Exception
+    */
+   private PageCursorProvider lookupCursorProvider() throws Exception
+   {
+      return lookupPageStore(ADDRESS).getCursorProvier();
+   }
+
+   /**
+    * @param storage
+    * @param pageStore
+    * @param pgParameter
+    * @param start
+    * @param NUM_MESSAGES
+    * @param messageSize
+    * @throws Exception
+    */
+   private Transaction pgMessages(StorageManager storage,
+                           PagingStoreImpl pageStore,
+                           long pgParameter,
+                           int start,
+                           final int NUM_MESSAGES,
+                           final int messageSize) throws Exception
+   {
+      
+      TransactionImpl txImpl = new TransactionImpl(pgParameter, null, storage);
+      
+      RoutingContext ctx = generateCTX(txImpl);
+
+      for (int i = start; i < start + NUM_MESSAGES; i++)
+      {
+         HornetQBuffer buffer = RandomUtil.randomBuffer(messageSize, i + 1l);
+         ServerMessage msg = new ServerMessageImpl(storage.generateUniqueID(), buffer.writerIndex());
+         msg.getBodyBuffer().writeBytes(buffer, 0, buffer.writerIndex());
+         msg.putIntProperty("key", i);
+         pageStore.page(msg, ctx, ctx.getContextListing(ADDRESS));
+      }
+      
+      return txImpl;
+
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Added: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/paging/PagePositionTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/paging/PagePositionTest.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/paging/PagePositionTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.integration.paging;
+
+import org.hornetq.tests.util.ServiceTestBase;
+
+/**
+ * A PageCursorTest
+ *
+ * @author <a href="mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class PagePositionTest extends ServiceTestBase
+{
+
+   // Test what would happen on redelivery situations
+   public void testRedeliverLike()
+   {
+      
+   }
+   
+   public void testRedeliverPersistence()
+   {
+      
+   }
+   
+   public void testDeletePagesAfterRedelivery()
+   {
+      
+   }
+   
+   public void testNextAfterPosition()
+   {
+      
+   }
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/persistence/DeleteMessagesOnStartupTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/persistence/DeleteMessagesOnStartupTest.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/persistence/DeleteMessagesOnStartupTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -76,7 +76,7 @@
 
       journal.loadBindingJournal(new ArrayList<QueueBindingInfo>(), new ArrayList<GroupingInfo>());
       
-      journal.loadMessageJournal(new FakePostOffice(), null, null, queues, null);
+      journal.loadMessageJournal(new FakePostOffice(), null, null, queues, null, null);
 
       assertEquals(98, deletedMessage.size());
       

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/persistence/RestartSMTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/persistence/RestartSMTest.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/persistence/RestartSMTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -101,7 +101,7 @@
 
          Map<Long, Queue> queues = new HashMap<Long, Queue>();
 
-         journal.loadMessageJournal(postOffice, null, null, queues, null);
+         journal.loadMessageJournal(postOffice, null, null, queues, null, null);
 
          journal.stop();
 
@@ -111,7 +111,7 @@
 
          queues = new HashMap<Long, Queue>();
 
-         journal.loadMessageJournal(postOffice, null, null, queues, null);
+         journal.loadMessageJournal(postOffice, null, null, queues, null, null);
 
          queueBindingInfos = new ArrayList<QueueBindingInfo>();
 

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/persistence/StorageManagerTestBase.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/persistence/StorageManagerTestBase.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/persistence/StorageManagerTestBase.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -128,7 +128,7 @@
       
       Map<Long, Queue> queues = new HashMap<Long, Queue>();
 
-      journal.loadMessageJournal(new FakePostOffice(), null, null, queues, null);
+      journal.loadMessageJournal(new FakePostOffice(), null, null, queues, null, null);
    }
 
    /**

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/replication/ReplicationTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/replication/ReplicationTest.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/integration/replication/ReplicationTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -288,7 +288,7 @@
 
          replicatedJournal.appendAddRecordTransactional(23, 24, (byte)1, new FakeData());
 
-         PagedMessage pgmsg = new PagedMessageImpl(msg, -1);
+         PagedMessage pgmsg = new PagedMessageImpl(msg, new long[0]);
          manager.pageWrite(pgmsg, 1);
          manager.pageWrite(pgmsg, 2);
          manager.pageWrite(pgmsg, 3);

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/timing/core/server/impl/QueueImplTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/timing/core/server/impl/QueueImplTest.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/timing/core/server/impl/QueueImplTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -70,6 +70,7 @@
                                   new SimpleString("address1"),
                                   new SimpleString("queue1"),
                                   null,
+                                  null,
                                   false,
                                   true,
                                   scheduledExecutor,
@@ -145,6 +146,7 @@
                                   new SimpleString("address1"),
                                   new SimpleString("queue1"),
                                   null,
+                                  null,
                                   false,
                                   true,
                                   scheduledExecutor,
@@ -253,6 +255,7 @@
                                   new SimpleString("address1"),
                                   QueueImplTest.queue1,
                                   null,
+                                  null,
                                   false,
                                   true,
                                   scheduledExecutor,

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PageImplTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PageImplTest.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PageImplTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -106,10 +106,10 @@
 
       for (int i = 0; i < msgs.size(); i++)
       {
-         Assert.assertEquals(simpleDestination, msgs.get(i).getMessage(null).getAddress());
+         Assert.assertEquals(simpleDestination, msgs.get(i).getMessage().getAddress());
 
          UnitTestCase.assertEqualsByteArrays(buffers.get(i).toByteBuffer().array(), msgs.get(i)
-                                                                                        .getMessage(null)
+                                                                                        .getMessage()
                                                                                         .getBodyBuffer()
                                                                                         .toByteBuffer()
                                                                                         .array());
@@ -178,10 +178,10 @@
 
       for (int i = 0; i < msgs.size(); i++)
       {
-         Assert.assertEquals(simpleDestination, msgs.get(i).getMessage(null).getAddress());
+         Assert.assertEquals(simpleDestination, msgs.get(i).getMessage().getAddress());
 
          UnitTestCase.assertEqualsByteArrays(buffers.get(i).toByteBuffer().array(), msgs.get(i)
-                                                                                        .getMessage(null)
+                                                                                        .getMessage()
                                                                                         .getBodyBuffer()
                                                                                         .toByteBuffer()
                                                                                         .array());
@@ -223,7 +223,7 @@
 
          msg.setAddress(simpleDestination);
 
-         page.write(new PagedMessageImpl(msg));
+         page.write(new PagedMessageImpl(msg, new long [0]));
 
          Assert.assertEquals(initialNumberOfMessages + i + 1, page.getNumberOfMessages());
       }

Added: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PagePositionTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PagePositionTest.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PagePositionTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.unit.core.paging.impl;
+
+import org.hornetq.tests.util.UnitTestCase;
+
+/**
+ * A PagePositionTest
+ *
+ * @author <a href="mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class PagePositionTest extends UnitTestCase
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+   
+   public void testNextSequenceOf()
+   {
+      
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingManagerImplTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingManagerImplTest.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingManagerImplTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -28,6 +28,7 @@
 import org.hornetq.core.paging.impl.TestSupportPageStore;
 import org.hornetq.core.persistence.impl.nullpm.NullStorageManager;
 import org.hornetq.core.server.ServerMessage;
+import org.hornetq.core.server.impl.RoutingContextImpl;
 import org.hornetq.core.server.impl.ServerMessageImpl;
 import org.hornetq.core.settings.HierarchicalRepository;
 import org.hornetq.core.settings.impl.AddressFullMessagePolicy;
@@ -81,11 +82,11 @@
 
       ServerMessage msg = createMessage(1l, new SimpleString("simple-test"), createRandomBuffer(10));
 
-      Assert.assertFalse(store.page(msg));
+      Assert.assertFalse(store.page(msg, new RoutingContextImpl(null)));
 
       store.startPaging();
 
-      Assert.assertTrue(store.page(msg));
+      Assert.assertTrue(store.page(msg, new RoutingContextImpl(null)));
 
       Page page = store.depage();
 
@@ -98,7 +99,7 @@
       Assert.assertEquals(1, msgs.size());
 
       UnitTestCase.assertEqualsByteArrays(msg.getBodyBuffer().writerIndex(), msg.getBodyBuffer().toByteBuffer().array(), msgs.get(0)
-                                                                                          .getMessage(null)
+                                                                                          .getMessage()
                                                                                           .getBodyBuffer()
                                                                                           .toByteBuffer()
                                                                                           .array());
@@ -107,7 +108,7 @@
 
       Assert.assertNull(store.depage());
 
-      Assert.assertFalse(store.page(msg));
+      Assert.assertFalse(store.page(msg, new RoutingContextImpl(null)));
    }
 
    // Package protected ---------------------------------------------

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingStoreImplTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingStoreImplTest.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingStoreImplTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -46,6 +46,7 @@
 import org.hornetq.core.paging.PagingManager;
 import org.hornetq.core.paging.PagingStore;
 import org.hornetq.core.paging.PagingStoreFactory;
+import org.hornetq.core.paging.cursor.PagePosition;
 import org.hornetq.core.paging.impl.PageTransactionInfoImpl;
 import org.hornetq.core.paging.impl.PagingStoreImpl;
 import org.hornetq.core.paging.impl.TestSupportPageStore;
@@ -63,6 +64,7 @@
 import org.hornetq.core.server.Queue;
 import org.hornetq.core.server.ServerMessage;
 import org.hornetq.core.server.group.impl.GroupBinding;
+import org.hornetq.core.server.impl.RoutingContextImpl;
 import org.hornetq.core.server.impl.ServerMessageImpl;
 import org.hornetq.core.settings.HierarchicalRepository;
 import org.hornetq.core.settings.impl.AddressFullMessagePolicy;
@@ -72,6 +74,7 @@
 import org.hornetq.tests.unit.core.server.impl.fakes.FakePostOffice;
 import org.hornetq.tests.util.RandomUtil;
 import org.hornetq.tests.util.UnitTestCase;
+import org.hornetq.utils.ExecutorFactory;
 import org.hornetq.utils.UUID;
 
 /**
@@ -142,7 +145,7 @@
                                                   null,
                                                   PagingStoreImplTest.destinationTestName,
                                                   addressSettings,
-                                                  executor,
+                                                  getExecutorFactory(),
                                                   true);
 
       storeImpl.start();
@@ -178,7 +181,7 @@
                                                            storeFactory,
                                                            PagingStoreImplTest.destinationTestName,
                                                            addressSettings,
-                                                           executor,
+                                                           getExecutorFactory(),
                                                            true);
 
       storeImpl.start();
@@ -200,7 +203,7 @@
 
       Assert.assertTrue(storeImpl.isPaging());
 
-      Assert.assertTrue(storeImpl.page(msg));
+      Assert.assertTrue(storeImpl.page(msg, new RoutingContextImpl(null)));
 
       Assert.assertEquals(1, storeImpl.getNumberOfPages());
 
@@ -214,12 +217,12 @@
                                       null,
                                       PagingStoreImplTest.destinationTestName,
                                       addressSettings,
-                                      executor,
+                                      getExecutorFactory(),
                                       true);
 
       storeImpl.start();
 
-      Assert.assertEquals(2, storeImpl.getNumberOfPages());
+      Assert.assertEquals(1, storeImpl.getNumberOfPages());
 
    }
 
@@ -241,7 +244,7 @@
                                                            storeFactory,
                                                            PagingStoreImplTest.destinationTestName,
                                                            addressSettings,
-                                                           executor,
+                                                           getExecutorFactory(),
                                                            true);
 
       storeImpl.start();
@@ -263,7 +266,7 @@
 
          ServerMessage msg = createMessage(i, storeImpl, destination, buffer);
 
-         Assert.assertTrue(storeImpl.page(msg));
+         Assert.assertTrue(storeImpl.page(msg, new RoutingContextImpl(null)));
       }
 
       Assert.assertEquals(1, storeImpl.getNumberOfPages());
@@ -288,7 +291,7 @@
       for (int i = 0; i < numMessages; i++)
       {
          HornetQBuffer horn1 = buffers.get(i);
-         HornetQBuffer horn2 = msg.get(i).getMessage(null).getBodyBuffer();
+         HornetQBuffer horn2 = msg.get(i).getMessage().getBodyBuffer();
          horn1.resetReaderIndex();
          horn2.resetReaderIndex();
          for (int j = 0; j < horn1.writerIndex(); j++)
@@ -316,7 +319,7 @@
                                                            storeFactory,
                                                            PagingStoreImplTest.destinationTestName,
                                                            addressSettings,
-                                                           executor,
+                                                           getExecutorFactory(),
                                                            true);
 
       storeImpl.start();
@@ -343,7 +346,7 @@
 
          ServerMessage msg = createMessage(i, storeImpl, destination, buffer);
 
-         Assert.assertTrue(storeImpl.page(msg));
+         Assert.assertTrue(storeImpl.page(msg, new RoutingContextImpl(null)));
       }
 
       Assert.assertEquals(2, storeImpl.getNumberOfPages());
@@ -355,6 +358,8 @@
       for (int pageNr = 0; pageNr < 2; pageNr++)
       {
          Page page = storeImpl.depage();
+         
+         System.out.println("numberOfPages = " + storeImpl.getNumberOfPages());
 
          page.open();
 
@@ -366,10 +371,8 @@
 
          for (int i = 0; i < 5; i++)
          {
-            Assert.assertEquals(sequence++, msg.get(i).getMessage(null).getMessageID());
-            UnitTestCase.assertEqualsBuffers(18, buffers.get(pageNr * 5 + i), msg.get(i)
-                                                                                 .getMessage(null)
-                                                                                 .getBodyBuffer());
+            Assert.assertEquals(sequence++, msg.get(i).getMessage().getMessageID());
+            UnitTestCase.assertEqualsBuffers(18, buffers.get(pageNr * 5 + i), msg.get(i).getMessage().getBodyBuffer());
          }
       }
 
@@ -379,7 +382,7 @@
 
       ServerMessage msg = createMessage(1, storeImpl, destination, buffers.get(0));
 
-      Assert.assertTrue(storeImpl.page(msg));
+      Assert.assertTrue(storeImpl.page(msg, new RoutingContextImpl(null)));
 
       Page newPage = storeImpl.depage();
 
@@ -397,11 +400,11 @@
 
       Assert.assertFalse(storeImpl.isPaging());
 
-      Assert.assertFalse(storeImpl.page(msg));
+      Assert.assertFalse(storeImpl.page(msg, new RoutingContextImpl(null)));
 
       storeImpl.startPaging();
 
-      Assert.assertTrue(storeImpl.page(msg));
+      Assert.assertTrue(storeImpl.page(msg, new RoutingContextImpl(null)));
 
       Page page = storeImpl.depage();
 
@@ -411,9 +414,9 @@
 
       Assert.assertEquals(1, msgs.size());
 
-      Assert.assertEquals(1l, msgs.get(0).getMessage(null).getMessageID());
+      Assert.assertEquals(1l, msgs.get(0).getMessage().getMessageID());
 
-      UnitTestCase.assertEqualsBuffers(18, buffers.get(0), msgs.get(0).getMessage(null).getBodyBuffer());
+      UnitTestCase.assertEqualsBuffers(18, buffers.get(0), msgs.get(0).getMessage().getBodyBuffer());
 
       Assert.assertEquals(1, storeImpl.getNumberOfPages());
 
@@ -463,7 +466,7 @@
                                                                  storeFactory,
                                                                  new SimpleString("test"),
                                                                  settings,
-                                                                 executor,
+                                                                 getExecutorFactory(),
                                                                  true);
 
       storeImpl.start();
@@ -497,7 +500,7 @@
                   // This is possible because the depage thread is not actually reading the pages.
                   // Just using the internal API to remove it from the page file system
                   ServerMessage msg = createMessage(id, storeImpl, destination, createRandomBuffer(id, 5));
-                  if (storeImpl.page(msg))
+                  if (storeImpl.page(msg, new RoutingContextImpl(null)))
                   {
                      buffers.put(id, msg);
                   }
@@ -592,14 +595,14 @@
 
          for (PagedMessage msg : msgs)
          {
-            long id = msg.getMessage(null).getBodyBuffer().readLong();
-            msg.getMessage(null).getBodyBuffer().resetReaderIndex();
+            long id = msg.getMessage().getBodyBuffer().readLong();
+            msg.getMessage().getBodyBuffer().resetReaderIndex();
 
             ServerMessage msgWritten = buffers.remove(id);
-            buffers2.put(id, msg.getMessage(null));
+            buffers2.put(id, msg.getMessage());
             Assert.assertNotNull(msgWritten);
-            Assert.assertEquals(msg.getMessage(null).getAddress(), msgWritten.getAddress());
-            UnitTestCase.assertEqualsBuffers(10, msgWritten.getBodyBuffer(), msg.getMessage(null).getBodyBuffer());
+            Assert.assertEquals(msg.getMessage().getAddress(), msgWritten.getAddress());
+            UnitTestCase.assertEqualsBuffers(10, msgWritten.getBodyBuffer(), msg.getMessage().getBodyBuffer());
          }
       }
 
@@ -626,7 +629,7 @@
                                                             storeFactory,
                                                             new SimpleString("test"),
                                                             settings,
-                                                            executor,
+                                                            getExecutorFactory(),
                                                             true);
       storeImpl2.start();
 
@@ -641,8 +644,10 @@
 
       long lastMessageId = messageIdGenerator.incrementAndGet();
       ServerMessage lastMsg = createMessage(lastMessageId, storeImpl, destination, createRandomBuffer(lastMessageId, 5));
+      
+      storeImpl2.forceAnotherPage();
 
-      storeImpl2.page(lastMsg);
+      storeImpl2.page(lastMsg, new RoutingContextImpl(null));
       buffers2.put(lastMessageId, lastMsg);
 
       Page lastPage = null;
@@ -665,13 +670,13 @@
          for (PagedMessage msg : msgs)
          {
 
-            long id = msg.getMessage(null).getBodyBuffer().readLong();
+            long id = msg.getMessage().getBodyBuffer().readLong();
             ServerMessage msgWritten = buffers2.remove(id);
             Assert.assertNotNull(msgWritten);
-            Assert.assertEquals(msg.getMessage(null).getAddress(), msgWritten.getAddress());
+            Assert.assertEquals(msg.getMessage().getAddress(), msgWritten.getAddress());
             UnitTestCase.assertEqualsByteArrays(msgWritten.getBodyBuffer().writerIndex(),
                                                 msgWritten.getBodyBuffer().toByteBuffer().array(),
-                                                msg.getMessage(null).getBodyBuffer().toByteBuffer().array());
+                                                msg.getMessage().getBodyBuffer().toByteBuffer().array());
          }
       }
 
@@ -680,14 +685,54 @@
       lastPage.close();
       Assert.assertEquals(1, lastMessages.size());
 
-      lastMessages.get(0).getMessage(null).getBodyBuffer().resetReaderIndex();
-      Assert.assertEquals(lastMessages.get(0).getMessage(null).getBodyBuffer().readLong(), lastMessageId);
+      lastMessages.get(0).getMessage().getBodyBuffer().resetReaderIndex();
+      Assert.assertEquals(lastMessages.get(0).getMessage().getBodyBuffer().readLong(), lastMessageId);
 
       Assert.assertEquals(0, buffers2.size());
 
       Assert.assertEquals(0, storeImpl.getAddressSize());
    }
 
+   public void testRestartPage() throws Throwable
+   {
+      clearData();
+      SequentialFileFactory factory = new NIOSequentialFileFactory(this.getPageDir());
+
+      PagingStoreFactory storeFactory = new FakeStoreFactory(factory);
+
+      final int MAX_SIZE = 1024 * 10;
+
+      AddressSettings settings = new AddressSettings();
+      settings.setPageSizeBytes(MAX_SIZE);
+      settings.setAddressFullMessagePolicy(AddressFullMessagePolicy.PAGE);
+
+      final TestSupportPageStore storeImpl = new PagingStoreImpl(PagingStoreImplTest.destinationTestName,
+                                                                 createMockManager(),
+                                                                 createStorageManagerMock(),
+                                                                 createPostOfficeMock(),
+                                                                 factory,
+                                                                 storeFactory,
+                                                                 new SimpleString("test"),
+                                                                 settings,
+                                                                 getExecutorFactory(),
+                                                                 true);
+
+      storeImpl.start();
+
+      Assert.assertEquals(0, storeImpl.getNumberOfPages());
+
+      // Marked the store to be paged
+      storeImpl.startPaging();
+
+      storeImpl.depage();
+
+      assertNull(storeImpl.getCurrentPage());
+
+      storeImpl.startPaging();
+
+      assertNotNull(storeImpl.getCurrentPage());
+   }
+
    public void testOrderOnPaging() throws Throwable
    {
       clearData();
@@ -709,7 +754,7 @@
                                                                  storeFactory,
                                                                  new SimpleString("test"),
                                                                  settings,
-                                                                 executor,
+                                                                 getExecutorFactory(),
                                                                  true);
 
       storeImpl.start();
@@ -750,7 +795,7 @@
                   // Just using the internal API to remove it from the page file system
                   ServerMessage msg = createMessage(i, storeImpl, destination, createRandomBuffer(i, 1024));
                   msg.putLongProperty("count", i);
-                  while (!storeImpl.page(msg))
+                  while (!storeImpl.page(msg, new RoutingContextImpl(null)))
                   {
                      storeImpl.startPaging();
                   }
@@ -791,22 +836,22 @@
                   {
                      page.open();
                      List<PagedMessage> messages = page.read();
- 
+
                      for (PagedMessage pgmsg : messages)
                      {
-                        ServerMessage msg = pgmsg.getMessage(null);
+                        ServerMessage msg = pgmsg.getMessage();
 
                         assertEquals(msgsRead++, msg.getMessageID());
 
                         assertEquals(msg.getMessageID(), msg.getLongProperty("count").longValue());
                      }
- 
+
                      page.close();
                      page.delete();
                   }
                   else
                   {
-                     System.out.println("Depaged!!!!");
+                     System.out.println("Depaged!!!! numerOfMessages = " + msgsRead + " of " + NUMBER_OF_MESSAGES);
                      Thread.sleep(500);
                   }
                }
@@ -830,7 +875,7 @@
 
       storeImpl.stop();
 
-      for (Throwable e: errors)
+      for (Throwable e : errors)
       {
          throw e;
       }
@@ -854,6 +899,18 @@
       return new FakePostOffice();
    }
 
+   private ExecutorFactory getExecutorFactory()
+   {
+      return new ExecutorFactory()
+      {
+
+         public Executor getExecutor()
+         {
+            return executor;
+         }
+      };
+   }
+
    private ServerMessage createMessage(final long id,
                                        final PagingStore store,
                                        final SimpleString destination,
@@ -873,18 +930,9 @@
       return msg;
    }
 
-   private HornetQBuffer createRandomBuffer(final long id, final int size)
+   protected HornetQBuffer createRandomBuffer(final long id, final int size)
    {
-      HornetQBuffer buffer = HornetQBuffers.fixedBuffer(size + 8);
-
-      buffer.writeLong(id);
-
-      for (int j = 8; j < buffer.capacity(); j++)
-      {
-         buffer.writeByte((byte)66);
-      }
-
-      return buffer;
+      return RandomUtil.randomBuffer(size, id);
    }
 
    // Protected ----------------------------------------------------
@@ -1035,6 +1083,15 @@
          return null;
       }
 
+      /* (non-Javadoc)
+       * @see org.hornetq.core.paging.PagingManager#processReload()
+       */
+      public void processReload()
+      {
+         // TODO Auto-generated method stub
+
+      }
+
    }
 
    class FakeStorageManager implements StorageManager
@@ -1162,6 +1219,7 @@
                                                        final PagingManager pagingManager,
                                                        final ResourceManager resourceManager,
                                                        final Map<Long, Queue> queues,
+                                                       Map<Long, QueueBindingInfo> queueInfos,
                                                        final Map<SimpleString, List<Pair<byte[], Long>>> duplicateIDMap) throws Exception
       {
          return new JournalLoadInformation();
@@ -1510,6 +1568,42 @@
       {
       }
 
+      /* (non-Javadoc)
+       * @see org.hornetq.core.persistence.StorageManager#storeCursorAcknowledge(long, org.hornetq.core.paging.cursor.PagePosition)
+       */
+      public void storeCursorAcknowledge(long queueID, PagePosition position)
+      {
+         // TODO Auto-generated method stub
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.persistence.StorageManager#storeCursorAcknowledgeTransactional(long, long, org.hornetq.core.paging.cursor.PagePosition)
+       */
+      public void storeCursorAcknowledgeTransactional(long txID, long queueID, PagePosition position)
+      {
+         // TODO Auto-generated method stub
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.persistence.StorageManager#deleteCursorAcknowledgeTransactional(long, long)
+       */
+      public void deleteCursorAcknowledgeTransactional(long txID, long ackID) throws Exception
+      {
+         // TODO Auto-generated method stub
+
+      }
+
+      /* (non-Javadoc)
+       * @see org.hornetq.core.persistence.StorageManager#updatePageTransaction(org.hornetq.core.paging.PageTransactionInfo, int)
+       */
+      public void updatePageTransaction(PageTransactionInfo pageTransaction, int depage) throws Exception
+      {
+         // TODO Auto-generated method stub
+
+      }
+
    }
 
    class FakeStoreFactory implements PagingStoreFactory
@@ -1546,7 +1640,7 @@
       /* (non-Javadoc)
        * @see org.hornetq.core.paging.PagingStoreFactory#newStore(org.hornetq.utils.SimpleString, org.hornetq.core.settings.impl.AddressSettings)
        */
-      public PagingStore newStore(final SimpleString destinationName, final AddressSettings addressSettings) throws Exception
+      public PagingStore newStore(final SimpleString destinationName, final AddressSettings addressSettings)
       {
          return null;
       }

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/postoffice/impl/BindingsImplTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/postoffice/impl/BindingsImplTest.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/postoffice/impl/BindingsImplTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -87,7 +87,7 @@
    {
       final FakeBinding fake = new FakeBinding(new SimpleString("a"));
 
-      final BindingsImpl bind = new BindingsImpl(null);
+      final BindingsImpl bind = new BindingsImpl(null, null);
       bind.addBinding(fake);
       bind.addBinding(new FakeBinding(new SimpleString("a")));
       bind.addBinding(new FakeBinding(new SimpleString("a")));

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/postoffice/impl/DuplicateDetectionUnitTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/postoffice/impl/DuplicateDetectionUnitTest.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/postoffice/impl/DuplicateDetectionUnitTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -111,6 +111,7 @@
                                     new FakePagingManager(),
                                     new ResourceManagerImpl(0, 0, scheduledThreadPool),
                                     new HashMap<Long, Queue>(),
+                                    null,
                                     mapDups);
 
          Assert.assertEquals(0, mapDups.size());
@@ -132,6 +133,7 @@
                                     new FakePagingManager(),
                                     new ResourceManagerImpl(0, 0, scheduledThreadPool),
                                     new HashMap<Long, Queue>(),
+                                    null,
                                     mapDups);
 
          Assert.assertEquals(1, mapDups.size());
@@ -160,6 +162,7 @@
                                     new FakePagingManager(),
                                     new ResourceManagerImpl(0, 0, scheduledThreadPool),
                                     new HashMap<Long, Queue>(),
+                                    null,
                                     mapDups);
 
          Assert.assertEquals(1, mapDups.size());
@@ -320,6 +323,16 @@
          return null;
       }
 
+      
+      
+      
+      /* (non-Javadoc)
+       * @see org.hornetq.core.paging.PagingManager#processReload()
+       */
+      public void processReload()
+      {
+      }
+
    }
 
 }

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/postoffice/impl/FakeQueue.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/postoffice/impl/FakeQueue.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/postoffice/impl/FakeQueue.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -20,6 +20,7 @@
 
 import org.hornetq.api.core.SimpleString;
 import org.hornetq.core.filter.Filter;
+import org.hornetq.core.paging.cursor.PageSubscription;
 import org.hornetq.core.server.Consumer;
 import org.hornetq.core.server.MessageReference;
 import org.hornetq.core.server.Queue;
@@ -91,10 +92,18 @@
    }
 
    private final SimpleString name;
+   
+   private final long id;
 
    public FakeQueue(final SimpleString name)
    {
+      this(name, 0);
+   }
+   
+   public FakeQueue(final SimpleString name, final long id)
+   {
       this.name = name;
+      this.id = id;
    }
 
    /* (non-Javadoc)
@@ -359,8 +368,7 @@
     */
    public long getID()
    {
-      // TODO Auto-generated method stub
-      return 0;
+      return id;
    }
 
    /* (non-Javadoc)
@@ -597,4 +605,13 @@
       
    }
 
+   /* (non-Javadoc)
+    * @see org.hornetq.core.server.Queue#getPageSubscription()
+    */
+   public PageSubscription getPageSubscription()
+   {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
 }
\ No newline at end of file

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/server/impl/fakes/FakeQueueFactory.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/server/impl/fakes/FakeQueueFactory.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/core/server/impl/fakes/FakeQueueFactory.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -19,6 +19,7 @@
 
 import org.hornetq.api.core.SimpleString;
 import org.hornetq.core.filter.Filter;
+import org.hornetq.core.paging.cursor.PageSubscription;
 import org.hornetq.core.postoffice.PostOffice;
 import org.hornetq.core.server.Queue;
 import org.hornetq.core.server.QueueFactory;
@@ -43,6 +44,7 @@
                             final SimpleString address,
                             final SimpleString name,
                             final Filter filter,
+                            final PageSubscription subscription,
                             final boolean durable,
                             final boolean temporary)
    {
@@ -50,6 +52,7 @@
                            address,
                            name,
                            filter,
+                           subscription,
                            durable,
                            temporary,
                            scheduledExecutor,

Added: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/util/SoftValueMapTest.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/util/SoftValueMapTest.java	                        (rev 0)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/unit/util/SoftValueMapTest.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2010 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.unit.util;
+
+import org.hornetq.tests.util.UnitTestCase;
+import org.hornetq.utils.SoftValueHashMap;
+
+/**
+ * A SoftValueMapTest
+ *
+ * @author <a href="mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ *
+ *
+ */
+public class SoftValueMapTest extends UnitTestCase
+{
+
+   // Constants -----------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   // Public --------------------------------------------------------
+
+   public void testEvictions()
+   {
+      forceGC();
+      long maxMemory = Runtime.getRuntime().maxMemory() - Runtime.getRuntime().freeMemory();
+      
+      // each buffer will be 1/10th of the maxMemory
+      int bufferSize = (int)(maxMemory / 100);
+      
+      SoftValueHashMap<Long, byte[]> softCache = new SoftValueHashMap<Long, byte[]>();
+      
+      final int MAX_ELEMENTS = 10000;
+      
+      for (long i = 0 ; i < MAX_ELEMENTS; i++)
+      {
+         softCache.put(i, new byte[bufferSize]);
+      }
+      
+      
+      assertTrue(softCache.size() < 100);
+      
+      System.out.println("Soft cache has " + softCache.size() + " elements");
+   }
+
+   
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/util/RandomUtil.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/util/RandomUtil.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/util/RandomUtil.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -18,6 +18,8 @@
 
 import javax.transaction.xa.Xid;
 
+import org.hornetq.api.core.HornetQBuffer;
+import org.hornetq.api.core.HornetQBuffers;
 import org.hornetq.api.core.SimpleString;
 import org.hornetq.core.transaction.impl.XidImpl;
 
@@ -72,7 +74,27 @@
       return Math.abs(RandomUtil.randomInt());
    }
    
+
+   public static HornetQBuffer randomBuffer(final int size, final long... data)
+   {
+      HornetQBuffer buffer = HornetQBuffers.fixedBuffer(size + 8 * data.length);
+
+      for (long d : data)
+      {
+         buffer.writeLong(d);
+      }
+
+      for (int i = 0 ; i < size; i++)
+      {
+         buffer.writeByte((byte)randomByte());
+      }
+
+      return buffer;
+   }
+
+
    
+   
    public static int randomInterval(final int min, final int max)
    {
       return min + randomMax(max - min);

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/util/ServiceTestBase.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/util/ServiceTestBase.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/util/ServiceTestBase.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -25,6 +25,7 @@
 import org.hornetq.api.core.TransportConfiguration;
 import org.hornetq.api.core.client.ClientMessage;
 import org.hornetq.api.core.client.ClientSession;
+import org.hornetq.api.core.client.ClientSessionFactory;
 import org.hornetq.api.core.client.HornetQClient;
 import org.hornetq.core.client.impl.ClientSessionFactoryImpl;
 import org.hornetq.core.config.Configuration;
@@ -334,6 +335,15 @@
          return createInVMFactory();
       }
    }
+   
+   protected void createQueue(String address, String queue) throws Exception
+   {
+      ClientSessionFactory sf = createInVMFactory();
+      ClientSession session = sf.createSession();
+      session.createQueue(address, queue);
+      session.close();
+      sf.close();
+   }
 
    protected ClientSessionFactoryImpl createInVMFactory()
    {

Modified: branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/util/UnitTestCase.java
===================================================================
--- branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/util/UnitTestCase.java	2010-11-15 20:57:55 UTC (rev 9890)
+++ branches/Branch_New_Paging_preMerge/tests/src/org/hornetq/tests/util/UnitTestCase.java	2010-11-15 21:09:22 UTC (rev 9891)
@@ -26,6 +26,7 @@
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
 import java.net.ServerSocket;
 import java.nio.ByteBuffer;
@@ -168,7 +169,7 @@
       }
    }
 
-   public static void forceGC(WeakReference<?> ref, long timeout)
+   public static void forceGC(Reference<?> ref, long timeout)
    {
       long waitUntil = System.currentTimeMillis() + timeout; 
       // A loop that will wait GC, using the minimal time as possible



More information about the hornetq-commits mailing list