JBoss hornetq SVN: r9893 - in branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core: server/impl and 1 other directory.
by do-not-reply@jboss.org
Author: clebert.suconic(a)jboss.com
Date: 2010-11-16 10:27:14 -0500 (Tue, 16 Nov 2010)
New Revision: 9893
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/server/impl/QueueImpl.java
Log:
Fixing tests
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-16 03:57:19 UTC (rev 9892)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/client/impl/ClientConsumerImpl.java 2010-11-16 15:27:14 UTC (rev 9893)
@@ -323,8 +323,12 @@
{
if (isBrowseOnly())
{
- log.warn("receive timeout is not effective on browsing, ignoring timeout");
- return receive(0, true);
+ ClientMessage msg = receive(timeout, false);
+ if (msg == null)
+ {
+ msg = receive(0, true);
+ }
+ return msg;
}
else
{
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-16 03:57:19 UTC (rev 9892)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/impl/QueueImpl.java 2010-11-16 15:27:14 UTC (rev 9893)
@@ -1255,7 +1255,7 @@
}
}
- if (messageReferences.size() == 0 && pageIterator.hasNext())
+ if (pageIterator != null && messageReferences.size() == 0 && pageIterator.hasNext())
{
scheduleDepage();
}
14 years, 1 month
JBoss hornetq SVN: r9892 - branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/cluster/impl.
by do-not-reply@jboss.org
Author: clebert.suconic(a)jboss.com
Date: 2010-11-15 22:57:19 -0500 (Mon, 15 Nov 2010)
New Revision: 9892
Modified:
branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/cluster/impl/RemoteQueueBindingImpl.java
Log:
One line is all that takes to ruin a monday for any programmer
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 21:09:22 UTC (rev 9891)
+++ branches/Branch_New_Paging_preMerge/src/main/org/hornetq/core/server/cluster/impl/RemoteQueueBindingImpl.java 2010-11-16 03:57:19 UTC (rev 9892)
@@ -207,7 +207,7 @@
{
// 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
- durableQueuesOnContext.add(storeAndForwardQueue);
+ context.addQueue(address, storeAndForwardQueue);
}
}
14 years, 1 month
JBoss hornetq SVN: r9891 - in branches/Branch_New_Paging_preMerge: src/main/org/hornetq/core/client/impl and 27 other directories.
by do-not-reply@jboss.org
Author: clebert.suconic(a)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@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@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@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@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@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@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@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@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@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@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@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@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@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@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
14 years, 1 month
JBoss hornetq SVN: r9890 - branches.
by do-not-reply@jboss.org
Author: clebert.suconic(a)jboss.com
Date: 2010-11-15 15:57:55 -0500 (Mon, 15 Nov 2010)
New Revision: 9890
Added:
branches/Branch_New_Paging_preMerge/
Log:
creating new branch to help with merging
Copied: branches/Branch_New_Paging_preMerge (from rev 9889, trunk)
14 years, 1 month
JBoss hornetq SVN: r9889 - branches/Branch_New_Paging/src/main/org/hornetq/core/server/impl.
by do-not-reply@jboss.org
Author: clebert.suconic(a)jboss.com
Date: 2010-11-15 13:32:03 -0500 (Mon, 15 Nov 2010)
New Revision: 9889
Modified:
branches/Branch_New_Paging/src/main/org/hornetq/core/server/impl/QueueImpl.java
Log:
fixing tests
Modified: branches/Branch_New_Paging/src/main/org/hornetq/core/server/impl/QueueImpl.java
===================================================================
--- branches/Branch_New_Paging/src/main/org/hornetq/core/server/impl/QueueImpl.java 2010-11-15 18:22:27 UTC (rev 9888)
+++ branches/Branch_New_Paging/src/main/org/hornetq/core/server/impl/QueueImpl.java 2010-11-15 18:32:03 UTC (rev 9889)
@@ -1316,7 +1316,8 @@
{
ServerMessage message = reference.getMessage();
- if (message.isDurable() && durable)
+ // TODO: DeliveryCount on paging
+ if (message.isDurable() && durable && !reference.isPaged())
{
storageManager.updateDeliveryCount(reference);
}
14 years, 1 month
JBoss hornetq SVN: r9888 - in branches/Branch_New_Paging: tests/src/org/hornetq/tests/unit/core/paging/impl and 1 other directory.
by do-not-reply@jboss.org
Author: clebert.suconic(a)jboss.com
Date: 2010-11-15 13:22:27 -0500 (Mon, 15 Nov 2010)
New Revision: 9888
Modified:
branches/Branch_New_Paging/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java
branches/Branch_New_Paging/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingStoreImplTest.java
Log:
Fixing tests
Modified: branches/Branch_New_Paging/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java
===================================================================
--- branches/Branch_New_Paging/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java 2010-11-15 01:38:36 UTC (rev 9887)
+++ branches/Branch_New_Paging/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java 2010-11-15 18:22:27 UTC (rev 9888)
@@ -654,6 +654,7 @@
// The current page is empty... which means we reached the end of the pages
if (returnPage.getNumberOfMessages() == 0)
{
+ stopPaging();
returnPage.open();
returnPage.delete();
Modified: branches/Branch_New_Paging/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingStoreImplTest.java
===================================================================
--- branches/Branch_New_Paging/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingStoreImplTest.java 2010-11-15 01:38:36 UTC (rev 9887)
+++ branches/Branch_New_Paging/tests/src/org/hornetq/tests/unit/core/paging/impl/PagingStoreImplTest.java 2010-11-15 18:22:27 UTC (rev 9888)
@@ -222,7 +222,7 @@
storeImpl.start();
- Assert.assertEquals(2, storeImpl.getNumberOfPages());
+ Assert.assertEquals(1, storeImpl.getNumberOfPages());
}
@@ -358,6 +358,8 @@
for (int pageNr = 0; pageNr < 2; pageNr++)
{
Page page = storeImpl.depage();
+
+ System.out.println("numberOfPages = " + storeImpl.getNumberOfPages());
page.open();
@@ -370,9 +372,7 @@
for (int i = 0; i < 5; i++)
{
Assert.assertEquals(sequence++, msg.get(i).getMessage().getMessageID());
- UnitTestCase.assertEqualsBuffers(18, buffers.get(pageNr * 5 + i), msg.get(i)
- .getMessage()
- .getBodyBuffer());
+ UnitTestCase.assertEqualsBuffers(18, buffers.get(pageNr * 5 + i), msg.get(i).getMessage().getBodyBuffer());
}
}
@@ -644,6 +644,8 @@
long lastMessageId = messageIdGenerator.incrementAndGet();
ServerMessage lastMsg = createMessage(lastMessageId, storeImpl, destination, createRandomBuffer(lastMessageId, 5));
+
+ storeImpl2.forceAnotherPage();
storeImpl2.page(lastMsg, new RoutingContextImpl(null));
buffers2.put(lastMessageId, lastMsg);
@@ -691,6 +693,46 @@
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();
@@ -794,7 +836,7 @@
{
page.open();
List<PagedMessage> messages = page.read();
-
+
for (PagedMessage pgmsg : messages)
{
ServerMessage msg = pgmsg.getMessage();
@@ -803,13 +845,13 @@
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);
}
}
@@ -833,7 +875,7 @@
storeImpl.stop();
- for (Throwable e: errors)
+ for (Throwable e : errors)
{
throw e;
}
@@ -856,15 +898,15 @@
{
return new FakePostOffice();
}
-
+
private ExecutorFactory getExecutorFactory()
{
return new ExecutorFactory()
{
-
+
public Executor getExecutor()
{
- return executor;
+ return executor;
}
};
}
@@ -1047,7 +1089,7 @@
public void processReload()
{
// TODO Auto-generated method stub
-
+
}
}
@@ -1532,7 +1574,7 @@
public void storeCursorAcknowledge(long queueID, PagePosition position)
{
// TODO Auto-generated method stub
-
+
}
/* (non-Javadoc)
@@ -1541,7 +1583,7 @@
public void storeCursorAcknowledgeTransactional(long txID, long queueID, PagePosition position)
{
// TODO Auto-generated method stub
-
+
}
/* (non-Javadoc)
@@ -1550,7 +1592,7 @@
public void deleteCursorAcknowledgeTransactional(long txID, long ackID) throws Exception
{
// TODO Auto-generated method stub
-
+
}
/* (non-Javadoc)
@@ -1559,7 +1601,7 @@
public void updatePageTransaction(PageTransactionInfo pageTransaction, int depage) throws Exception
{
// TODO Auto-generated method stub
-
+
}
}
14 years, 1 month
JBoss hornetq SVN: r9887 - in branches/Branch_Large_Message_Compression: tests/src/org/hornetq/tests/integration/client and 1 other directories.
by do-not-reply@jboss.org
Author: gaohoward
Date: 2010-11-14 20:38:36 -0500 (Sun, 14 Nov 2010)
New Revision: 9887
Added:
branches/Branch_Large_Message_Compression/tests/src/org/hornetq/tests/integration/client/LargeMessageCompressTest.java
branches/Branch_Large_Message_Compression/tests/src/org/hornetq/tests/unit/util/GZipUtilTest.java
Modified:
branches/Branch_Large_Message_Compression/src/main/org/hornetq/utils/GZipUtil.java
Log:
some test
Modified: branches/Branch_Large_Message_Compression/src/main/org/hornetq/utils/GZipUtil.java
===================================================================
--- branches/Branch_Large_Message_Compression/src/main/org/hornetq/utils/GZipUtil.java 2010-11-13 06:04:44 UTC (rev 9886)
+++ branches/Branch_Large_Message_Compression/src/main/org/hornetq/utils/GZipUtil.java 2010-11-15 01:38:36 UTC (rev 9887)
@@ -16,7 +16,6 @@
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -373,7 +372,7 @@
System.out.println("----total output: " + counter);
*/
- unzip();
+ zip();
/*
FileInputStream input = new FileInputStream("/home/howard/tmp/jbm.log.1");
FileOutputStream output = new FileOutputStream("/home/howard/tmp/output.zip");
Added: branches/Branch_Large_Message_Compression/tests/src/org/hornetq/tests/integration/client/LargeMessageCompressTest.java
===================================================================
--- branches/Branch_Large_Message_Compression/tests/src/org/hornetq/tests/integration/client/LargeMessageCompressTest.java (rev 0)
+++ branches/Branch_Large_Message_Compression/tests/src/org/hornetq/tests/integration/client/LargeMessageCompressTest.java 2010-11-15 01:38:36 UTC (rev 9887)
@@ -0,0 +1,2817 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.hornetq.tests.integration.client;
+
+import java.util.HashMap;
+
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import junit.framework.Assert;
+
+import org.hornetq.api.core.Message;
+import org.hornetq.api.core.SimpleString;
+import org.hornetq.api.core.client.*;
+import org.hornetq.core.client.impl.ClientConsumerInternal;
+import org.hornetq.core.config.Configuration;
+import org.hornetq.core.logging.Logger;
+import org.hornetq.core.persistence.impl.journal.JournalStorageManager;
+import org.hornetq.core.persistence.impl.journal.LargeServerMessageImpl;
+import org.hornetq.core.server.HornetQServer;
+import org.hornetq.core.server.Queue;
+import org.hornetq.core.settings.impl.AddressSettings;
+import org.hornetq.tests.integration.largemessage.LargeMessageTestBase;
+import org.hornetq.tests.util.RandomUtil;
+import org.hornetq.tests.util.UnitTestCase;
+
+/**
+ * A LargeMessageCompressTest
+ *
+ * Originally this class was copied from LargeMessageTest, with some irrelevant tests
+ * removed. All tests that works with
+ * normal large message transport should also work with compression flag turned on.
+ *
+ * @author <a href="mailto:hgao@redhat.com">Howard Gao</a>
+ *
+ *
+ */
+public class LargeMessageCompressTest extends LargeMessageTestBase
+{
+ // Constants -----------------------------------------------------
+
+ final static int RECEIVE_WAIT_TIME = 60000;
+
+ private final int LARGE_MESSAGE_SIZE = 20 * 1024;
+
+ // Attributes ----------------------------------------------------
+
+ static final SimpleString ADDRESS = new SimpleString("SimpleAddress");
+
+ // Static --------------------------------------------------------
+ private final Logger log = Logger.getLogger(LargeMessageTest.class);
+
+ // Constructors --------------------------------------------------
+
+ // Public --------------------------------------------------------
+
+ protected boolean isNetty()
+ {
+ return false;
+ }
+
+ public void testCloseConsumer() throws Exception
+ {
+ final int messageSize = (int)(3.5 * HornetQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
+
+ ClientSession session = null;
+
+ try
+ {
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ session = sf.createSession(false, false, false);
+
+ session.createTemporaryQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ Message clientFile = createLargeClientMessage(session, messageSize, true);
+
+ producer.send(clientFile);
+
+ session.commit();
+
+ session.start();
+
+ ClientConsumer consumer = session.createConsumer(LargeMessageTest.ADDRESS);
+ ClientMessage msg1 = consumer.receive(1000);
+ msg1.acknowledge();
+ session.commit();
+ Assert.assertNotNull(msg1);
+
+ consumer.close();
+
+ try
+ {
+ msg1.getBodyBuffer().readByte();
+ Assert.fail("Exception was expected");
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ session.close();
+
+ validateNoFilesOnLargeDir();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+ }
+
+ public void testDLALargeMessage() throws Exception
+ {
+ final int messageSize = (int)(3.5 * HornetQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
+
+ ClientSession session = null;
+
+ try
+ {
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ session = sf.createSession(false, false, false);
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, true);
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS.concat("-2"), true);
+
+ SimpleString ADDRESS_DLA = LargeMessageTest.ADDRESS.concat("-dla");
+
+ AddressSettings addressSettings = new AddressSettings();
+
+ addressSettings.setDeadLetterAddress(ADDRESS_DLA);
+ addressSettings.setMaxDeliveryAttempts(1);
+
+ server.getAddressSettingsRepository().addMatch("*", addressSettings);
+
+ session.createQueue(ADDRESS_DLA, ADDRESS_DLA, true);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ Message clientFile = createLargeClientMessage(session, messageSize, true);
+
+ producer.send(clientFile);
+
+ session.commit();
+
+ session.start();
+
+ ClientConsumer consumer = session.createConsumer(ADDRESS_DLA);
+
+ ClientConsumer consumerRollback = session.createConsumer(LargeMessageTest.ADDRESS);
+ ClientMessage msg1 = consumerRollback.receive(1000);
+ Assert.assertNotNull(msg1);
+ msg1.acknowledge();
+ session.rollback();
+ consumerRollback.close();
+
+ msg1 = consumer.receive(10000);
+
+ Assert.assertNotNull(msg1);
+
+ for (int i = 0; i < messageSize; i++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(i), msg1.getBodyBuffer().readByte());
+ }
+
+ session.close();
+ server.stop();
+
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ session = sf.createSession(false, false, false);
+
+ session.start();
+
+ consumer = session.createConsumer(ADDRESS_DLA);
+
+ msg1 = consumer.receive(10000);
+
+ Assert.assertNotNull(msg1);
+
+ for (int i = 0; i < messageSize; i++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(i), msg1.getBodyBuffer().readByte());
+ }
+
+ msg1.acknowledge();
+
+ session.commit();
+
+ validateNoFilesOnLargeDir(1);
+
+ consumer = session.createConsumer(LargeMessageTest.ADDRESS.concat("-2"));
+
+ msg1 = consumer.receive(10000);
+
+ Assert.assertNotNull(msg1);
+
+ for (int i = 0; i < messageSize; i++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(i), msg1.getBodyBuffer().readByte());
+ }
+
+ msg1.acknowledge();
+
+ session.commit();
+
+ session.close();
+
+ validateNoFilesOnLargeDir();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+ }
+
+ public void testDeliveryCount() throws Exception
+ {
+ final int messageSize = (int)(3.5 * HornetQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
+
+ ClientSession session = null;
+
+ try
+ {
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ session = sf.createSession(false, false, false);
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, true);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ Message clientFile = createLargeClientMessage(session, messageSize, true);
+ producer.send(clientFile);
+
+ session.commit();
+
+ session.start();
+
+ ClientConsumer consumer = session.createConsumer(LargeMessageTest.ADDRESS);
+
+ ClientMessage msg = consumer.receive(10000);
+ Assert.assertNotNull(msg);
+ msg.acknowledge();
+ Assert.assertEquals(1, msg.getDeliveryCount());
+
+ log.info("body buffer is " + msg.getBodyBuffer());
+
+ for (int i = 0; i < messageSize; i++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(i), msg.getBodyBuffer().readByte());
+ }
+ session.rollback();
+
+ session.close();
+
+ session = sf.createSession(false, false, false);
+ session.start();
+
+ consumer = session.createConsumer(LargeMessageTest.ADDRESS);
+ msg = consumer.receive(10000);
+ Assert.assertNotNull(msg);
+ msg.acknowledge();
+ for (int i = 0; i < messageSize; i++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(i), msg.getBodyBuffer().readByte());
+ }
+ Assert.assertEquals(2, msg.getDeliveryCount());
+ msg.acknowledge();
+ consumer.close();
+
+ session.commit();
+
+ validateNoFilesOnLargeDir();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+ }
+
+ public void testDLAOnExpiryNonDurableMessage() throws Exception
+ {
+ final int messageSize = (int)(3.5 * HornetQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
+
+ ClientSession session = null;
+
+ try
+ {
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ SimpleString ADDRESS_DLA = LargeMessageTest.ADDRESS.concat("-dla");
+ SimpleString ADDRESS_EXPIRY = LargeMessageTest.ADDRESS.concat("-expiry");
+
+ AddressSettings addressSettings = new AddressSettings();
+
+ addressSettings.setDeadLetterAddress(ADDRESS_DLA);
+ addressSettings.setExpiryAddress(ADDRESS_EXPIRY);
+ addressSettings.setMaxDeliveryAttempts(1);
+
+ server.getAddressSettingsRepository().addMatch("*", addressSettings);
+
+ session = sf.createSession(false, false, false);
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, true);
+
+ session.createQueue(ADDRESS_DLA, ADDRESS_DLA, true);
+ session.createQueue(ADDRESS_EXPIRY, ADDRESS_EXPIRY, true);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ Message clientFile = createLargeClientMessage(session, messageSize, false);
+ clientFile.setExpiration(System.currentTimeMillis());
+
+ producer.send(clientFile);
+
+ session.commit();
+
+ session.start();
+
+ ClientConsumer consumerExpired = session.createConsumer(LargeMessageTest.ADDRESS);
+ // to kick expiry quicker than waiting reaper thread
+ Assert.assertNull(consumerExpired.receiveImmediate());
+ consumerExpired.close();
+
+ ClientConsumer consumerExpiry = session.createConsumer(ADDRESS_EXPIRY);
+
+ ClientMessage msg1 = consumerExpiry.receive(5000);
+ Assert.assertNotNull(msg1);
+ msg1.acknowledge();
+
+ session.rollback();
+
+ for (int j = 0; j < messageSize; j++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(j), msg1.getBodyBuffer().readByte());
+ }
+
+ consumerExpiry.close();
+
+ for (int i = 0; i < 10; i++)
+ {
+
+ consumerExpiry = session.createConsumer(ADDRESS_DLA);
+
+ msg1 = consumerExpiry.receive(5000);
+ Assert.assertNotNull(msg1);
+ msg1.acknowledge();
+
+ session.rollback();
+
+ for (int j = 0; j < messageSize; j++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(j), msg1.getBodyBuffer().readByte());
+ }
+
+ consumerExpiry.close();
+ }
+
+ session.close();
+
+ session = sf.createSession(false, false, false);
+
+ session.start();
+
+ consumerExpiry = session.createConsumer(ADDRESS_DLA);
+
+ msg1 = consumerExpiry.receive(5000);
+
+ Assert.assertNotNull(msg1);
+
+ msg1.acknowledge();
+
+ for (int i = 0; i < messageSize; i++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(i), msg1.getBodyBuffer().readByte());
+ }
+
+ session.commit();
+
+ consumerExpiry.close();
+
+ session.commit();
+
+ session.close();
+
+ server.stop();
+
+ server.start();
+
+ validateNoFilesOnLargeDir();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+ }
+
+ public void testDLAOnExpiry() throws Exception
+ {
+ final int messageSize = (int)(3.5 * HornetQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
+
+ ClientSession session = null;
+
+ try
+ {
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ SimpleString ADDRESS_DLA = LargeMessageTest.ADDRESS.concat("-dla");
+ SimpleString ADDRESS_EXPIRY = LargeMessageTest.ADDRESS.concat("-expiry");
+
+ AddressSettings addressSettings = new AddressSettings();
+
+ addressSettings.setDeadLetterAddress(ADDRESS_DLA);
+ addressSettings.setExpiryAddress(ADDRESS_EXPIRY);
+ addressSettings.setMaxDeliveryAttempts(1);
+
+ server.getAddressSettingsRepository().addMatch("*", addressSettings);
+
+ session = sf.createSession(false, false, false);
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, true);
+
+ session.createQueue(ADDRESS_DLA, ADDRESS_DLA, true);
+ session.createQueue(ADDRESS_EXPIRY, ADDRESS_EXPIRY, true);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ Message clientFile = createLargeClientMessage(session, messageSize, true);
+ clientFile.setExpiration(System.currentTimeMillis());
+
+ producer.send(clientFile);
+
+ session.commit();
+
+ session.start();
+
+ ClientConsumer consumerExpired = session.createConsumer(LargeMessageTest.ADDRESS);
+ // to kick expiry quicker than waiting reaper thread
+ Assert.assertNull(consumerExpired.receiveImmediate());
+ consumerExpired.close();
+
+ ClientConsumer consumerExpiry = session.createConsumer(ADDRESS_EXPIRY);
+
+ ClientMessage msg1 = consumerExpiry.receive(5000);
+ Assert.assertNotNull(msg1);
+ msg1.acknowledge();
+
+ session.rollback();
+
+ for (int j = 0; j < messageSize; j++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(j), msg1.getBodyBuffer().readByte());
+ }
+
+ consumerExpiry.close();
+
+ for (int i = 0; i < 10; i++)
+ {
+ consumerExpiry = session.createConsumer(ADDRESS_DLA);
+
+ msg1 = consumerExpiry.receive(5000);
+ Assert.assertNotNull(msg1);
+ msg1.acknowledge();
+
+ session.rollback();
+
+ for (int j = 0; j < messageSize; j++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(j), msg1.getBodyBuffer().readByte());
+ }
+
+ consumerExpiry.close();
+ }
+
+ session.close();
+ server.stop();
+
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ sf = createFactory(isNetty());
+
+ session = sf.createSession(false, false, false);
+
+ session.start();
+
+ consumerExpiry = session.createConsumer(ADDRESS_DLA);
+
+ msg1 = consumerExpiry.receive(5000);
+ Assert.assertNotNull(msg1);
+ msg1.acknowledge();
+
+ for (int i = 0; i < messageSize; i++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(i), msg1.getBodyBuffer().readByte());
+ }
+
+ session.commit();
+
+ consumerExpiry.close();
+
+ session.commit();
+
+ session.close();
+
+ validateNoFilesOnLargeDir();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+ }
+
+ public void testExpiryLargeMessage() throws Exception
+ {
+ final int messageSize = 3 * HornetQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE;
+
+ ClientSession session = null;
+
+ try
+ {
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ AddressSettings addressSettings = new AddressSettings();
+
+ SimpleString ADDRESS_EXPIRY = LargeMessageTest.ADDRESS.concat("-expiry");
+
+ addressSettings.setExpiryAddress(ADDRESS_EXPIRY);
+
+ server.getAddressSettingsRepository().addMatch("*", addressSettings);
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ session = sf.createSession(false, false, false);
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, true);
+
+ session.createQueue(ADDRESS_EXPIRY, ADDRESS_EXPIRY, true);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ Message clientFile = createLargeClientMessage(session, messageSize, true);
+
+ clientFile.setExpiration(System.currentTimeMillis());
+
+ producer.send(clientFile);
+
+ session.commit();
+
+ session.start();
+
+ ClientConsumer consumer = session.createConsumer(ADDRESS_EXPIRY);
+
+ // Creating a consumer just to make the expiry process go faster and not have to wait for the reaper
+ ClientConsumer consumer2 = session.createConsumer(LargeMessageTest.ADDRESS);
+ Assert.assertNull(consumer2.receiveImmediate());
+
+ ClientMessage msg1 = consumer.receive(50000);
+
+ Assert.assertNotNull(msg1);
+
+ for (int i = 0; i < messageSize; i++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(i), msg1.getBodyBuffer().readByte());
+ }
+
+ session.close();
+ server.stop();
+
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ sf = createFactory(isNetty());
+
+ session = sf.createSession(false, false, false);
+
+ session.start();
+
+ consumer = session.createConsumer(ADDRESS_EXPIRY);
+
+ msg1 = consumer.receive(10000);
+
+ Assert.assertNotNull(msg1);
+
+ for (int i = 0; i < messageSize; i++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(i), msg1.getBodyBuffer().readByte());
+ }
+
+ msg1.acknowledge();
+
+ session.commit();
+
+ session.close();
+
+ validateNoFilesOnLargeDir();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+ }
+
+ public void testResendSmallStreamMessage() throws Exception
+ {
+ internalTestResendMessage(50000);
+ }
+
+ public void testResendLargeStreamMessage() throws Exception
+ {
+ internalTestResendMessage(150 * 1024);
+ }
+
+ public void internalTestResendMessage(final long messageSize) throws Exception
+ {
+ ClientSession session = null;
+
+ try
+ {
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ session = sf.createSession(false, false, false);
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, true);
+
+ SimpleString ADDRESS2 = LargeMessageTest.ADDRESS.concat("-2");
+
+ session.createQueue(ADDRESS2, ADDRESS2, true);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ ClientProducer producer2 = session.createProducer(ADDRESS2);
+
+ Message clientFile = createLargeClientMessage(session, messageSize, false);
+
+ producer.send(clientFile);
+
+ session.commit();
+
+ session.start();
+
+ ClientConsumer consumer = session.createConsumer(LargeMessageTest.ADDRESS);
+ ClientConsumer consumer2 = session.createConsumer(ADDRESS2);
+
+ ClientMessage msg1 = consumer.receive(10000);
+ msg1.acknowledge();
+
+ producer2.send(msg1);
+
+ boolean failed = false;
+
+ try
+ {
+ producer2.send(msg1);
+ }
+ catch (Throwable e)
+ {
+ failed = true;
+ }
+
+ Assert.assertTrue("Exception expected", failed);
+
+ session.commit();
+
+ ClientMessage msg2 = consumer2.receive(10000);
+
+ Assert.assertNotNull(msg2);
+
+ msg2.acknowledge();
+
+ session.commit();
+
+ Assert.assertEquals(messageSize, msg2.getBodySize());
+
+ compareString(messageSize, msg2);
+
+ session.close();
+
+ validateNoFilesOnLargeDir();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+ }
+
+ public void testResendCachedSmallStreamMessage() throws Exception
+ {
+ internalTestResendMessage(50000);
+ }
+
+ public void testResendCachedLargeStreamMessage() throws Exception
+ {
+ internalTestCachedResendMessage(150 * 1024);
+ }
+
+ public void internalTestCachedResendMessage(final long messageSize) throws Exception
+ {
+ ClientSession session = null;
+
+ try
+ {
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ sf.setMinLargeMessageSize(111);
+
+ sf.setCacheLargeMessagesClient(true);
+
+ session = sf.createSession(false, false, false);
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, true);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ Message originalMsg = createLargeClientMessage(session, messageSize, false);
+
+ producer.send(originalMsg);
+
+ session.commit();
+
+ ClientConsumer consumer = session.createConsumer(LargeMessageTest.ADDRESS);
+
+ session.start();
+
+ ClientMessage msgReceived = consumer.receive(10000);
+ msgReceived.acknowledge();
+
+ session.commit();
+
+ compareString(messageSize, msgReceived);
+
+ msgReceived.getBodyBuffer().readerIndex(0);
+
+ producer.send(msgReceived);
+
+ session.commit();
+
+ ClientMessage msgReceived2 = consumer.receive(10000);
+
+ msgReceived2.acknowledge();
+
+ compareString(messageSize, msgReceived2);
+
+ session.commit();
+
+ session.close();
+
+ validateNoFilesOnLargeDir();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+ }
+
+ /**
+ * @param messageSize
+ * @param msg2
+ */
+ private void compareString(final long messageSize, ClientMessage msg)
+ {
+ assertNotNull(msg);
+ for (long i = 0; i < messageSize; i++)
+ {
+ Assert.assertEquals("position " + i, UnitTestCase.getSamplebyte(i), msg.getBodyBuffer().readByte());
+ }
+ }
+
+ public void testFilePersistenceOneHugeMessage() throws Exception
+ {
+ testChunks(false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ 1,
+ 100 * 1024l * 1024l,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0,
+ 10 * 1024 * 1024,
+ 1024 * 1024);
+ }
+
+ public void testFilePersistenceOneMessageStreaming() throws Exception
+ {
+ testChunks(false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ 1,
+ 100 * 1024l * 1024l,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceSmallMessageStreaming() throws Exception
+ {
+ testChunks(false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ 100,
+ 1024,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceOneHugeMessageConsumer() throws Exception
+ {
+ testChunks(false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ true,
+ 1,
+ 100 * 1024 * 1024,
+ 120000,
+ 0,
+ 10 * 1024 * 1024,
+ 1024 * 1024);
+ }
+
+ public void testFilePersistence() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceConsumer() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ 2,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceXA() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceXAStream() throws Exception
+ {
+ testChunks(true,
+ false,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ 1,
+ 1024 * 1024,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceXAStreamRestart() throws Exception
+ {
+ testChunks(true,
+ true,
+ false,
+ true,
+ true,
+ false,
+ false,
+ false,
+ false,
+ 1,
+ 1024 * 1024,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceXAConsumer() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceXAConsumerRestart() throws Exception
+ {
+ testChunks(true,
+ true,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceBlocked() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceBlockedConsumer() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceBlockedXA() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ false,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceBlockedXAConsumer() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceBlockedPreACK() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ 1,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceBlockedPreACKConsumer() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ 1,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceBlockedPreACKXA() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceBlockedPreACKXARestart() throws Exception
+ {
+ testChunks(true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ false,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceBlockedPreACKXAConsumer() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceBlockedPreACKXAConsumerRestart() throws Exception
+ {
+ testChunks(true,
+ true,
+ true,
+ false,
+ true,
+ true,
+ true,
+ true,
+ true,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testFilePersistenceDelayed() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ 1,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 2000);
+ }
+
+ public void testFilePersistenceDelayedConsumer() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ 1,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 2000);
+ }
+
+ public void testFilePersistenceDelayedXA() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ 1,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 2000);
+ }
+
+ public void testFilePersistenceDelayedXAConsumer() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ 1,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 2000);
+ }
+
+ public void testNullPersistence() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ 1,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testNullPersistenceConsumer() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ 1,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testNullPersistenceXA() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ 1,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testNullPersistenceXAConsumer() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ 1,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testNullPersistenceDelayed() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 100);
+ }
+
+ public void testNullPersistenceDelayedConsumer() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 100);
+ }
+
+ public void testNullPersistenceDelayedXA() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 100);
+ }
+
+ public void testNullPersistenceDelayedXAConsumer() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ 100,
+ LARGE_MESSAGE_SIZE,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 100);
+ }
+
+ public void testPageOnLargeMessage() throws Exception
+ {
+ testPageOnLargeMessage(true, false);
+ }
+
+ public void testSendSmallMessageXA() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ 100,
+ 4,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testSendSmallMessageXAConsumer() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ 100,
+ 4,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testSendSmallMessageNullPersistenceXA() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ false,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testSendSmallMessageNullPersistenceXAConsumer() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testSendRegularMessageNullPersistenceDelayed() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 1000);
+ }
+
+ public void testSendRegularMessageNullPersistenceDelayedConsumer() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 1000);
+ }
+
+ public void testSendRegularMessageNullPersistenceDelayedXA() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 1000);
+ }
+
+ public void testSendRegularMessageNullPersistenceDelayedXAConsumer() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 1000);
+ }
+
+ public void testSendRegularMessagePersistence() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testSendRegularMessagePersistenceConsumer() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testSendRegularMessagePersistenceXA() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ false,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testSendRegularMessagePersistenceXAConsumer() throws Exception
+ {
+ testChunks(true,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ true,
+ true,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 0);
+ }
+
+ public void testSendRegularMessagePersistenceDelayed() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 1000);
+ }
+
+ public void testSendRegularMessagePersistenceDelayedConsumer() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 1000);
+ }
+
+ public void testSendRegularMessagePersistenceDelayedXA() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ false,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 1000);
+ }
+
+ public void testSendRegularMessagePersistenceDelayedXAConsumer() throws Exception
+ {
+ testChunks(false,
+ false,
+ true,
+ false,
+ true,
+ false,
+ false,
+ false,
+ true,
+ 100,
+ 100,
+ LargeMessageTest.RECEIVE_WAIT_TIME,
+ 1000);
+ }
+
+ public void testTwoBindingsTwoStartedConsumers() throws Exception
+ {
+ // there are two bindings.. one is ACKed, the other is not, the server is restarted
+ // The other binding is acked... The file must be deleted
+
+ try
+ {
+
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ SimpleString queue[] = new SimpleString[] { new SimpleString("queue1"), new SimpleString("queue2") };
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ ClientSession session = sf.createSession(null, null, false, true, true, false, 0);
+
+ session.createQueue(LargeMessageTest.ADDRESS, queue[0], null, true);
+ session.createQueue(LargeMessageTest.ADDRESS, queue[1], null, true);
+
+ int numberOfBytes = 400000;
+
+ Message clientFile = createLargeClientMessage(session, numberOfBytes);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ session.start();
+
+ producer.send(clientFile);
+
+ producer.close();
+
+ ClientConsumer consumer = session.createConsumer(queue[1]);
+ ClientMessage msg = consumer.receive(LargeMessageTest.RECEIVE_WAIT_TIME);
+ Assert.assertNull(consumer.receiveImmediate());
+ Assert.assertNotNull(msg);
+
+ msg.acknowledge();
+ consumer.close();
+
+ log.debug("Stopping");
+
+ session.stop();
+
+ ClientConsumer consumer1 = session.createConsumer(queue[0]);
+
+ session.start();
+
+ msg = consumer1.receive(LargeMessageTest.RECEIVE_WAIT_TIME);
+ Assert.assertNotNull(msg);
+ msg.acknowledge();
+ consumer1.close();
+
+ session.commit();
+
+ session.close();
+
+ validateNoFilesOnLargeDir();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+
+ }
+
+ public void testTwoBindingsAndRestart() throws Exception
+ {
+ testTwoBindings(true);
+ }
+
+ public void testTwoBindingsNoRestart() throws Exception
+ {
+ testTwoBindings(false);
+ }
+
+ public void testTwoBindings(final boolean restart) throws Exception
+ {
+ // there are two bindings.. one is ACKed, the other is not, the server is restarted
+ // The other binding is acked... The file must be deleted
+
+ try
+ {
+
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ SimpleString queue[] = new SimpleString[] { new SimpleString("queue1"), new SimpleString("queue2") };
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ ClientSession session = sf.createSession(null, null, false, true, true, false, 0);
+
+ session.createQueue(LargeMessageTest.ADDRESS, queue[0], null, true);
+ session.createQueue(LargeMessageTest.ADDRESS, queue[1], null, true);
+
+ int numberOfBytes = 400000;
+
+ Message clientFile = createLargeClientMessage(session, numberOfBytes);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+ producer.send(clientFile);
+
+ producer.close();
+
+ readMessage(session, queue[1], numberOfBytes);
+
+ if (restart)
+ {
+ session.close();
+
+ server.stop();
+
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ sf = createFactory(isNetty());
+
+ session = sf.createSession(null, null, false, true, true, false, 0);
+ }
+
+ readMessage(session, queue[0], numberOfBytes);
+
+ session.close();
+
+ validateNoFilesOnLargeDir();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+
+ }
+
+ public void testSendRollbackXADurable() throws Exception
+ {
+ internalTestSendRollback(true, true);
+ }
+
+ public void testSendRollbackXANonDurable() throws Exception
+ {
+ internalTestSendRollback(true, false);
+ }
+
+ public void testSendRollbackDurable() throws Exception
+ {
+ internalTestSendRollback(false, true);
+ }
+
+ public void testSendRollbackNonDurable() throws Exception
+ {
+ internalTestSendRollback(false, false);
+ }
+
+ private void internalTestSendRollback(final boolean isXA, final boolean durable) throws Exception
+ {
+ ClientSession session = null;
+
+ try
+ {
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ session = sf.createSession(isXA, false, false);
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, true);
+
+ Xid xid = null;
+
+ if (isXA)
+ {
+ xid = RandomUtil.randomXid();
+ session.start(xid, XAResource.TMNOFLAGS);
+ }
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ Message clientFile = createLargeClientMessage(session, 50000, durable);
+
+ for (int i = 0; i < 1; i++)
+ {
+ producer.send(clientFile);
+ }
+
+ if (isXA)
+ {
+ session.end(xid, XAResource.TMSUCCESS);
+ session.prepare(xid);
+ session.close();
+ server.stop();
+ server.start();
+
+ session = sf.createSession(isXA, false, false);
+
+ session.rollback(xid);
+ }
+ else
+ {
+ session.rollback();
+ }
+
+ session.close();
+
+ validateNoFilesOnLargeDir();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+
+ }
+
+ public void testSimpleRollback() throws Exception
+ {
+ simpleRollbackInternalTest(false);
+ }
+
+ public void testSimpleRollbackXA() throws Exception
+ {
+ simpleRollbackInternalTest(true);
+ }
+
+ public void simpleRollbackInternalTest(final boolean isXA) throws Exception
+ {
+ // there are two bindings.. one is ACKed, the other is not, the server is restarted
+ // The other binding is acked... The file must be deleted
+
+ try
+ {
+
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ ClientSession session = sf.createSession(isXA, false, false);
+
+ Xid xid = null;
+
+ if (isXA)
+ {
+ xid = newXID();
+ session.start(xid, XAResource.TMNOFLAGS);
+ }
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, null, true);
+
+ int numberOfBytes = 200000;
+
+ session.start();
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ ClientConsumer consumer = session.createConsumer(LargeMessageTest.ADDRESS);
+
+ for (int n = 0; n < 10; n++)
+ {
+ Message clientFile = createLargeClientMessage(session, numberOfBytes, n % 2 == 0);
+
+ producer.send(clientFile);
+
+ Assert.assertNull(consumer.receiveImmediate());
+
+ if (isXA)
+ {
+ session.end(xid, XAResource.TMSUCCESS);
+ session.rollback(xid);
+ xid = newXID();
+ session.start(xid, XAResource.TMNOFLAGS);
+ }
+ else
+ {
+ session.rollback();
+ }
+
+ clientFile = createLargeClientMessage(session, numberOfBytes, n % 2 == 0);
+
+ producer.send(clientFile);
+
+ Assert.assertNull(consumer.receiveImmediate());
+
+ if (isXA)
+ {
+ session.end(xid, XAResource.TMSUCCESS);
+ session.commit(xid, true);
+ xid = newXID();
+ session.start(xid, XAResource.TMNOFLAGS);
+ }
+ else
+ {
+ session.commit();
+ }
+
+ for (int i = 0; i < 2; i++)
+ {
+
+ ClientMessage clientMessage = consumer.receive(5000);
+
+ Assert.assertNotNull(clientMessage);
+
+ Assert.assertEquals(numberOfBytes, clientMessage.getBodyBuffer().writerIndex());
+
+ clientMessage.acknowledge();
+
+ if (isXA)
+ {
+ if (i == 0)
+ {
+ session.end(xid, XAResource.TMSUCCESS);
+ session.prepare(xid);
+ session.rollback(xid);
+ xid = newXID();
+ session.start(xid, XAResource.TMNOFLAGS);
+ }
+ else
+ {
+ session.end(xid, XAResource.TMSUCCESS);
+ session.commit(xid, true);
+ xid = newXID();
+ session.start(xid, XAResource.TMNOFLAGS);
+ }
+ }
+ else
+ {
+ if (i == 0)
+ {
+ session.rollback();
+ }
+ else
+ {
+ session.commit();
+ }
+ }
+ }
+ }
+
+ session.close();
+
+ validateNoFilesOnLargeDir();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+
+ }
+
+ public void testBufferMultipleLargeMessages() throws Exception
+ {
+ ClientSession session = null;
+ HornetQServer server = null;
+
+ final int SIZE = 10 * 1024;
+ final int NUMBER_OF_MESSAGES = 30;
+ try
+ {
+
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ sf.setMinLargeMessageSize(1024);
+ sf.setConsumerWindowSize(1024 * 1024);
+
+ session = sf.createSession(null, null, false, false, false, false, 0);
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, null, true);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ for (int i = 0; i < NUMBER_OF_MESSAGES; i++)
+ {
+ ClientMessage clientFile = session.createMessage(true);
+ clientFile.setBodyInputStream(UnitTestCase.createFakeLargeStream(SIZE));
+ producer.send(clientFile);
+
+ }
+ session.commit();
+ producer.close();
+
+ session.start();
+
+ ClientConsumerInternal consumer = (ClientConsumerInternal)session.createConsumer(LargeMessageTest.ADDRESS);
+
+ // Wait the consumer to be complete with 10 messages before getting others
+ long timeout = System.currentTimeMillis() + 10000;
+ while (consumer.getBufferSize() < NUMBER_OF_MESSAGES && timeout > System.currentTimeMillis())
+ {
+ Thread.sleep(10);
+ }
+ Assert.assertEquals(NUMBER_OF_MESSAGES, consumer.getBufferSize());
+
+ // Reads the messages, rollback.. read them again
+ for (int trans = 0; trans < 2; trans++)
+ {
+
+ for (int i = 0; i < NUMBER_OF_MESSAGES; i++)
+ {
+ ClientMessage msg = consumer.receive(10000);
+ Assert.assertNotNull(msg);
+
+ // it will ignore the buffer (not read it) on the first try
+ if (trans == 0)
+ {
+ for (int byteRead = 0; byteRead < SIZE; byteRead++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(byteRead), msg.getBodyBuffer().readByte());
+ }
+ }
+
+ msg.acknowledge();
+ }
+ if (trans == 0)
+ {
+ session.rollback();
+ }
+ else
+ {
+ session.commit();
+ }
+ }
+
+ Assert.assertEquals(0,
+ ((Queue)server.getPostOffice().getBinding(LargeMessageTest.ADDRESS).getBindable()).getDeliveringCount());
+ Assert.assertEquals(0,
+ ((Queue)server.getPostOffice().getBinding(LargeMessageTest.ADDRESS).getBindable()).getMessageCount());
+
+ }
+ finally
+ {
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+ }
+
+ public void testReceiveMultipleMessages() throws Exception
+ {
+ ClientSession session = null;
+ HornetQServer server = null;
+
+ final int SIZE = 10 * 1024;
+ final int NUMBER_OF_MESSAGES = 1000;
+ try
+ {
+
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ sf.setMinLargeMessageSize(1024);
+ sf.setConsumerWindowSize(1024 * 1024);
+
+ session = sf.createSession(null, null, false, false, false, false, 0);
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, null, true);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ for (int i = 0; i < NUMBER_OF_MESSAGES; i++)
+ {
+ ClientMessage clientFile = session.createMessage(true);
+ clientFile.setBodyInputStream(UnitTestCase.createFakeLargeStream(SIZE));
+ producer.send(clientFile);
+
+ }
+ session.commit();
+ producer.close();
+
+ session.start();
+
+ // Reads the messages, rollback.. read them again
+ for (int trans = 0; trans < 2; trans++)
+ {
+
+ ClientConsumerInternal consumer = (ClientConsumerInternal)session.createConsumer(LargeMessageTest.ADDRESS);
+
+ // Wait the consumer to be complete with 10 messages before getting others
+ long timeout = System.currentTimeMillis() + 10000;
+ while (consumer.getBufferSize() < 10 && timeout > System.currentTimeMillis())
+ {
+ Thread.sleep(10);
+ }
+
+ for (int i = 0; i < NUMBER_OF_MESSAGES; i++)
+ {
+ ClientMessage msg = consumer.receive(10000);
+ Assert.assertNotNull(msg);
+
+ // it will ignore the buffer (not read it) on the first try
+ if (trans == 0)
+ {
+ for (int byteRead = 0; byteRead < SIZE; byteRead++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(byteRead), msg.getBodyBuffer().readByte());
+ }
+ }
+
+ msg.acknowledge();
+ }
+ if (trans == 0)
+ {
+ session.rollback();
+ }
+ else
+ {
+ session.commit();
+ }
+
+ consumer.close();
+ }
+
+ Assert.assertEquals(0,
+ ((Queue)server.getPostOffice().getBinding(LargeMessageTest.ADDRESS).getBindable()).getDeliveringCount());
+ Assert.assertEquals(0,
+ ((Queue)server.getPostOffice().getBinding(LargeMessageTest.ADDRESS).getBindable()).getMessageCount());
+
+ }
+ finally
+ {
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+ }
+
+ public void testSendStreamingSingleMessage() throws Exception
+ {
+ ClientSession session = null;
+ HornetQServer server = null;
+
+ final int SIZE = 10 * 1024 * 1024;
+ try
+ {
+
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ sf.setMinLargeMessageSize(100 * 1024);
+
+ session = sf.createSession(null, null, false, true, true, false, 0);
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, null, true);
+
+ ClientMessage clientFile = session.createMessage(true);
+ clientFile.setBodyInputStream(UnitTestCase.createFakeLargeStream(SIZE));
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ session.start();
+
+ log.debug("Sending");
+ producer.send(clientFile);
+
+ producer.close();
+
+ log.debug("Waiting");
+
+ ClientConsumer consumer = session.createConsumer(LargeMessageTest.ADDRESS);
+
+ ClientMessage msg2 = consumer.receive(10000);
+
+ msg2.acknowledge();
+
+ msg2.setOutputStream(createFakeOutputStream());
+ Assert.assertTrue(msg2.waitOutputStreamCompletion(60000));
+
+ session.commit();
+
+ Assert.assertEquals(0,
+ ((Queue)server.getPostOffice().getBinding(LargeMessageTest.ADDRESS).getBindable()).getDeliveringCount());
+ Assert.assertEquals(0,
+ ((Queue)server.getPostOffice().getBinding(LargeMessageTest.ADDRESS).getBindable()).getMessageCount());
+
+ }
+ finally
+ {
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+ }
+
+ /** Receive messages but never reads them, leaving the buffer pending */
+ public void testIgnoreStreaming() throws Exception
+ {
+ ClientSession session = null;
+ HornetQServer server = null;
+
+ final int SIZE = 10 * 1024;
+ final int NUMBER_OF_MESSAGES = 1;
+ try
+ {
+
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ sf.setMinLargeMessageSize(1024);
+
+ session = sf.createSession(null, null, false, true, true, false, 0);
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, null, true);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ for (int i = 0; i < NUMBER_OF_MESSAGES; i++)
+ {
+ ClientMessage msg = session.createMessage(true);
+ msg.setBodyInputStream(UnitTestCase.createFakeLargeStream(SIZE));
+ msg.putIntProperty(new SimpleString("key"), i);
+ producer.send(msg);
+
+ log.debug("Sent msg " + i);
+ }
+
+ session.start();
+
+ log.debug("Sending");
+
+ producer.close();
+
+ log.debug("Waiting");
+
+ ClientConsumer consumer = session.createConsumer(LargeMessageTest.ADDRESS);
+
+ for (int i = 0; i < NUMBER_OF_MESSAGES; i++)
+ {
+ ClientMessage msg = consumer.receive(50000);
+ Assert.assertNotNull(msg);
+
+ Assert.assertEquals(i, msg.getObjectProperty(new SimpleString("key")));
+
+ msg.acknowledge();
+ }
+
+ consumer.close();
+
+ session.commit();
+
+ Assert.assertEquals(0,
+ ((Queue)server.getPostOffice().getBinding(LargeMessageTest.ADDRESS).getBindable()).getDeliveringCount());
+ Assert.assertEquals(0,
+ ((Queue)server.getPostOffice().getBinding(LargeMessageTest.ADDRESS).getBindable()).getMessageCount());
+
+ log.debug("Thread done");
+ }
+ finally
+ {
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+ }
+
+ // The ClientConsumer should be able to also send ServerLargeMessages as that's done by the CoreBridge
+ public void testSendServerMessage() throws Exception
+ {
+ HornetQServer server = createServer(true);
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(false);
+ sf.setCompressLargeMessages(true);
+
+ ClientSession session = sf.createSession(false, false);
+
+ try
+ {
+ LargeServerMessageImpl fileMessage = new LargeServerMessageImpl((JournalStorageManager)server.getStorageManager());
+
+ fileMessage.setMessageID(1005);
+
+ for (int i = 0; i < LARGE_MESSAGE_SIZE; i++)
+ {
+ fileMessage.addBytes(new byte[] { UnitTestCase.getSamplebyte(i) });
+ }
+
+ fileMessage.releaseResources();
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, true);
+
+ ClientProducer prod = session.createProducer(LargeMessageTest.ADDRESS);
+
+ prod.send(fileMessage);
+
+ fileMessage.deleteFile();
+
+ session.commit();
+
+ session.start();
+
+ ClientConsumer cons = session.createConsumer(LargeMessageTest.ADDRESS);
+
+ ClientMessage msg = cons.receive(5000);
+
+ Assert.assertNotNull(msg);
+
+ Assert.assertEquals(msg.getBodySize(), LARGE_MESSAGE_SIZE);
+
+ for (int i = 0; i < LARGE_MESSAGE_SIZE; i++)
+ {
+ Assert.assertEquals(UnitTestCase.getSamplebyte(i), msg.getBodyBuffer().readByte());
+ }
+
+ msg.acknowledge();
+
+ session.commit();
+
+ }
+ finally
+ {
+ sf.close();
+ server.stop();
+ }
+ }
+
+ public void testLargeMessageCompression() throws Exception
+ {
+ final int messageSize = (int)(3.5 * HornetQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);
+
+ ClientSession session = null;
+
+ try
+ {
+ server = createServer(true, isNetty());
+
+ server.start();
+
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ session = sf.createSession(false, false, false);
+
+ session.createTemporaryQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ Message clientFile = createLargeClientMessage(session, messageSize, true);
+
+ producer.send(clientFile);
+
+ session.commit();
+
+ session.start();
+
+ ClientConsumer consumer = session.createConsumer(LargeMessageTest.ADDRESS);
+ ClientMessage msg1 = consumer.receive(1000);
+ Assert.assertNotNull(msg1);
+
+ for (int i = 0 ; i < messageSize; i++)
+ {
+ //System.out.print(msg1.getBodyBuffer().readByte() + " ");
+ //if (i % 100 == 0) System.out.println();
+ byte b = msg1.getBodyBuffer().readByte();
+ //System.out.println("Byte read: " + (char)b + " i " + i);
+ assertEquals("position = " + i, getSamplebyte(i), b);
+ }
+
+ msg1.acknowledge();
+ session.commit();
+
+ consumer.close();
+
+ session.close();
+
+ validateNoFilesOnLargeDir();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+
+ try
+ {
+ session.close();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+ }
+
+ // Package protected ---------------------------------------------
+
+ // Protected -----------------------------------------------------
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ clearData();
+ log.info("\n*********************************************************************************\n Starting " + getName() +
+ "\n*********************************************************************************");
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ log.info("\n*********************************************************************************\nDone with " + getName() +
+ "\n*********************************************************************************");
+ super.tearDown();
+ }
+
+ protected void testPageOnLargeMessage(final boolean realFiles, final boolean sendBlocking) throws Exception
+ {
+ Configuration config = createDefaultConfig(isNetty());
+
+ final int PAGE_MAX = 20 * 1024;
+
+ final int PAGE_SIZE = 10 * 1024;
+
+ HashMap<String, AddressSettings> map = new HashMap<String, AddressSettings>();
+
+ AddressSettings value = new AddressSettings();
+ map.put(LargeMessageTest.ADDRESS.toString(), value);
+ server = createServer(realFiles, config, PAGE_SIZE, PAGE_MAX, map);
+ server.start();
+
+ final int numberOfBytes = 1024;
+
+ final int numberOfBytesBigMessage = 400000;
+
+ try
+ {
+ ClientSessionFactory sf = createFactory(isNetty());
+ sf.setCompressLargeMessages(true);
+
+ if (sendBlocking)
+ {
+ sf.setBlockOnNonDurableSend(true);
+ sf.setBlockOnDurableSend(true);
+ sf.setBlockOnAcknowledge(true);
+ }
+
+ ClientSession session = sf.createSession(null, null, false, true, true, false, 0);
+
+ session.createQueue(LargeMessageTest.ADDRESS, LargeMessageTest.ADDRESS, null, true);
+
+ ClientProducer producer = session.createProducer(LargeMessageTest.ADDRESS);
+
+ ClientMessage message = null;
+
+ for (int i = 0; i < 100; i++)
+ {
+ message = session.createMessage(true);
+
+ // TODO: Why do I need to reset the writerIndex?
+ message.getBodyBuffer().writerIndex(0);
+
+ for (int j = 1; j <= numberOfBytes; j++)
+ {
+ message.getBodyBuffer().writeInt(j);
+ }
+
+ producer.send(message);
+ }
+
+ ClientMessage clientFile = createLargeClientMessage(session, numberOfBytesBigMessage);
+
+ producer.send(clientFile);
+
+ session.close();
+
+ if (realFiles)
+ {
+ server.stop();
+
+ server = createServer(true, config, PAGE_SIZE, PAGE_MAX, map);
+ server.start();
+
+ sf = createFactory(isNetty());
+ }
+
+ session = sf.createSession(null, null, false, true, true, false, 0);
+
+ ClientConsumer consumer = session.createConsumer(LargeMessageTest.ADDRESS);
+
+ session.start();
+
+ for (int i = 0; i < 100; i++)
+ {
+ ClientMessage message2 = consumer.receive(LargeMessageTest.RECEIVE_WAIT_TIME);
+
+ Assert.assertNotNull(message2);
+
+ message2.acknowledge();
+
+ Assert.assertNotNull(message2);
+
+ message.getBodyBuffer().readerIndex(0);
+
+ for (int j = 1; j <= numberOfBytes; j++)
+ {
+ Assert.assertEquals(j, message.getBodyBuffer().readInt());
+ }
+ }
+
+ consumer.close();
+
+ session.close();
+
+ session = sf.createSession(null, null, false, true, true, false, 0);
+
+ readMessage(session, LargeMessageTest.ADDRESS, numberOfBytesBigMessage);
+
+ // printBuffer("message received : ", message2.getBody());
+
+ session.close();
+ }
+ finally
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Throwable ignored)
+ {
+ }
+ }
+
+ }
+
+ // Private -------------------------------------------------------
+
+ // Inner classes -------------------------------------------------
+
+}
Added: branches/Branch_Large_Message_Compression/tests/src/org/hornetq/tests/unit/util/GZipUtilTest.java
===================================================================
--- branches/Branch_Large_Message_Compression/tests/src/org/hornetq/tests/unit/util/GZipUtilTest.java (rev 0)
+++ branches/Branch_Large_Message_Compression/tests/src/org/hornetq/tests/unit/util/GZipUtilTest.java 2010-11-15 01:38:36 UTC (rev 9887)
@@ -0,0 +1,129 @@
+/*
+ * 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 java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.Random;
+import java.util.zip.GZIPInputStream;
+
+import org.hornetq.core.logging.Logger;
+import org.hornetq.tests.util.UnitTestCase;
+import org.hornetq.utils.GZipUtil.GZipPipe;
+
+/**
+ * A GZipUtilTest
+ *
+ * @author Howard Gao
+ *
+ *
+ */
+public class GZipUtilTest extends UnitTestCase
+{
+ private static final Logger log = Logger.getLogger(GZipUtilTest.class);
+
+ //create a 10M file, zip it into another file
+ //then unzip it and compare the result with original file
+ public void testZipFunction() throws Exception
+ {
+ this.recreateDirectory(this.getTestDir());
+
+ File originalFile = new File(this.getTestDir(), "gzipUtilTest_file.txt");
+ File zippedFile = new File(this.getTestDir(), "gzipUtilTest_file.zip");
+
+ FileOutputStream originalOut = new FileOutputStream(originalFile);
+ FileOutputStream zippedOut = new FileOutputStream(zippedFile);
+
+ //now create the file
+ Random r = new Random();
+ final int size = 1024 * 10;
+ byte[] writeBuffer = new byte[1024];
+
+ for (int i = 0; i < size; i++)
+ {
+ int b = r.nextInt(256);
+ for (int j = 0; j < 1024; j++)
+ {
+ writeBuffer[j] = (byte)b;
+ }
+ originalOut.write(writeBuffer);
+ }
+ originalOut.close();
+
+ //now zip it
+ GZipPipe pipe = new GZipPipe(new FileInputStream(originalFile), 2048);
+ byte[] buffer = new byte[2048];
+
+ int n = pipe.read(buffer);
+ while (n != -1)
+ {
+ if (n > 0)
+ {
+ zippedOut.write(buffer, 0, n);
+ }
+ n = pipe.read(buffer);
+ }
+ zippedOut.close();
+
+ //now unzip it and compare
+ log.debug("zipped file Size: " + zippedFile.length());
+ GZIPInputStream zippedInput = new GZIPInputStream(new FileInputStream(zippedFile));
+ FileInputStream originalInput = new FileInputStream(originalFile);
+
+ ArrayList<Integer> fromZip = new ArrayList<Integer>();
+ ArrayList<Integer> original = new ArrayList<Integer>();
+
+ byte[] readBuffer = new byte[2048];
+ int count = zippedInput.read(readBuffer);
+
+ while (count != -1)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ fromZip.add(readBuffer[i] & 0xFF);
+ }
+ count = zippedInput.read(readBuffer);
+ }
+ zippedInput.close();
+
+ count = originalInput.read(readBuffer);
+ while (count != -1)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ original.add(readBuffer[i] & 0xFF);
+ }
+ count = originalInput.read(readBuffer);
+ }
+ originalInput.close();
+
+ log.debug("fromZip: " + fromZip.size());
+ compareByteArray(fromZip, original);
+
+ originalFile.delete();
+ zippedFile.delete();
+ }
+
+ private void compareByteArray(ArrayList<Integer> b1, ArrayList<Integer> b2)
+ {
+ assertEquals(b1.size(), b2.size());
+
+ for (int i = 0; i < b1.size(); i++)
+ {
+ assertEquals(b1.get(i), b2.get(i));
+ }
+ }
+}
14 years, 1 month
JBoss hornetq SVN: r9886 - branches/Branch_New_Paging/tests/src/org/hornetq/tests/integration/client.
by do-not-reply@jboss.org
Author: clebert.suconic(a)jboss.com
Date: 2010-11-13 01:04:44 -0500 (Sat, 13 Nov 2010)
New Revision: 9886
Modified:
branches/Branch_New_Paging/tests/src/org/hornetq/tests/integration/client/PagingTest.java
Log:
Renaming method
Modified: branches/Branch_New_Paging/tests/src/org/hornetq/tests/integration/client/PagingTest.java
===================================================================
--- branches/Branch_New_Paging/tests/src/org/hornetq/tests/integration/client/PagingTest.java 2010-11-13 05:38:12 UTC (rev 9885)
+++ branches/Branch_New_Paging/tests/src/org/hornetq/tests/integration/client/PagingTest.java 2010-11-13 06:04:44 UTC (rev 9886)
@@ -467,7 +467,7 @@
UnitTestCase.assertEqualsByteArrays(body, other);
}
-
+
/**
* - Make a destination in page mode
* - Add stuff to a transaction
@@ -998,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();
14 years, 1 month
JBoss hornetq SVN: r9885 - in branches/Branch_New_Paging: src/main/org/hornetq/core/paging/impl and 1 other directories.
by do-not-reply@jboss.org
Author: clebert.suconic(a)jboss.com
Date: 2010-11-13 00:38:12 -0500 (Sat, 13 Nov 2010)
New Revision: 9885
Modified:
branches/Branch_New_Paging/src/main/org/hornetq/core/paging/cursor/impl/PageCursorProviderImpl.java
branches/Branch_New_Paging/src/main/org/hornetq/core/paging/cursor/impl/PageSubscriptionImpl.java
branches/Branch_New_Paging/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java
branches/Branch_New_Paging/tests/src/org/hornetq/tests/integration/client/PagingTest.java
Log:
Fixing sort order
Modified: branches/Branch_New_Paging/src/main/org/hornetq/core/paging/cursor/impl/PageCursorProviderImpl.java
===================================================================
--- branches/Branch_New_Paging/src/main/org/hornetq/core/paging/cursor/impl/PageCursorProviderImpl.java 2010-11-13 02:43:47 UTC (rev 9884)
+++ branches/Branch_New_Paging/src/main/org/hornetq/core/paging/cursor/impl/PageCursorProviderImpl.java 2010-11-13 05:38:12 UTC (rev 9885)
@@ -23,7 +23,6 @@
import org.hornetq.core.logging.Logger;
import org.hornetq.core.paging.Page;
import org.hornetq.core.paging.PagedMessage;
-import org.hornetq.core.paging.PagingManager;
import org.hornetq.core.paging.PagingStore;
import org.hornetq.core.paging.cursor.PageCache;
import org.hornetq.core.paging.cursor.PageCursorProvider;
Modified: branches/Branch_New_Paging/src/main/org/hornetq/core/paging/cursor/impl/PageSubscriptionImpl.java
===================================================================
--- branches/Branch_New_Paging/src/main/org/hornetq/core/paging/cursor/impl/PageSubscriptionImpl.java 2010-11-13 02:43:47 UTC (rev 9884)
+++ branches/Branch_New_Paging/src/main/org/hornetq/core/paging/cursor/impl/PageSubscriptionImpl.java 2010-11-13 05:38:12 UTC (rev 9885)
@@ -24,6 +24,7 @@
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;
@@ -48,7 +49,6 @@
import org.hornetq.core.transaction.impl.TransactionImpl;
import org.hornetq.utils.ConcurrentHashSet;
import org.hornetq.utils.Future;
-import org.hornetq.utils.LinkedListImpl;
import org.hornetq.utils.LinkedListIterator;
/**
@@ -99,7 +99,7 @@
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 org.hornetq.utils.LinkedList<PagePosition> redeliveries = new LinkedListImpl<PagePosition>();
+ private final ConcurrentLinkedQueue<PagePosition> redeliveries = new ConcurrentLinkedQueue<PagePosition>();
// Static --------------------------------------------------------
@@ -464,7 +464,7 @@
{
synchronized (redeliveries)
{
- redeliveries.addTail(position);
+ redeliveries.add(position);
}
}
@@ -961,20 +961,16 @@
private PagePosition lastOperation = null;
- private final LinkedListIterator<PagePosition> redeliveryIterator;
-
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()
{
- synchronized (redeliveries)
- {
- redeliveryIterator = redeliveries.iterator();
- }
}
public void repeat()
@@ -983,7 +979,7 @@
{
synchronized (redeliveries)
{
- redeliveryIterator.repeat();
+ cachedNext = lastRedelivery;
}
}
else
@@ -1045,16 +1041,20 @@
{
synchronized (redeliveries)
{
- if (redeliveryIterator.hasNext())
+ 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(redeliveryIterator.next());
+ PagedReference redeliveredMsg = getReference(redelivery);
+ lastRedelivery = redeliveredMsg;
return redeliveredMsg;
}
else
{
+ lastRedelivery = null;
isredelivery = false;
}
@@ -1077,7 +1077,9 @@
valid = routed(message.getPagedMessage());
if (!valid)
+ {
ignored = true;
+ }
// 2nd ... if TX, is it committed?
if (valid && message.getPagedMessage().getTransactionID() != 0)
@@ -1171,7 +1173,10 @@
*/
public void remove()
{
- PageSubscriptionImpl.this.getPageInfo(position).remove(position);
+ if (!isredelivery)
+ {
+ PageSubscriptionImpl.this.getPageInfo(position).remove(position);
+ }
}
/* (non-Javadoc)
Modified: branches/Branch_New_Paging/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java
===================================================================
--- branches/Branch_New_Paging/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java 2010-11-13 02:43:47 UTC (rev 9884)
+++ branches/Branch_New_Paging/src/main/org/hornetq/core/paging/impl/PagingStoreImpl.java 2010-11-13 05:38:12 UTC (rev 9885)
@@ -14,9 +14,7 @@
package org.hornetq.core.paging.impl;
import java.text.DecimalFormat;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
@@ -43,7 +41,6 @@
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.RouteContextList;
import org.hornetq.core.server.RoutingContext;
import org.hornetq.core.server.ServerMessage;
@@ -53,7 +50,6 @@
import org.hornetq.core.transaction.Transaction.State;
import org.hornetq.core.transaction.TransactionOperation;
import org.hornetq.core.transaction.TransactionPropertyIndexes;
-import org.hornetq.core.transaction.impl.TransactionImpl;
import org.hornetq.utils.ExecutorFactory;
import org.hornetq.utils.Future;
@@ -1049,19 +1045,14 @@
{
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);
@@ -1072,6 +1063,13 @@
currentPageSize.set(0);
currentPage.open();
+
+ currentPageId = tmpCurrentPageId;
+
+ if (currentPageId < firstPageId)
+ {
+ firstPageId = currentPageId;
+ }
}
finally
{
Modified: branches/Branch_New_Paging/tests/src/org/hornetq/tests/integration/client/PagingTest.java
===================================================================
--- branches/Branch_New_Paging/tests/src/org/hornetq/tests/integration/client/PagingTest.java 2010-11-13 02:43:47 UTC (rev 9884)
+++ branches/Branch_New_Paging/tests/src/org/hornetq/tests/integration/client/PagingTest.java 2010-11-13 05:38:12 UTC (rev 9885)
@@ -966,7 +966,7 @@
ClientConsumer consumer = session.createConsumer(PagingTest.ADDRESS);
for (int i = 0; i < numberOfMessages; i++)
- {
+ {
ClientMessage msg = consumer.receive(5000);
assertNotNull(msg);
assertEquals(i, msg.getIntProperty("count").intValue());
14 years, 1 month
JBoss hornetq SVN: r9884 - in branches/Branch_New_Paging/src/main/org/hornetq/core: paging/impl and 1 other directories.
by do-not-reply@jboss.org
Author: clebert.suconic(a)jboss.com
Date: 2010-11-12 21:43:47 -0500 (Fri, 12 Nov 2010)
New Revision: 9884
Modified:
branches/Branch_New_Paging/src/main/org/hornetq/core/paging/cursor/impl/PageSubscriptionImpl.java
branches/Branch_New_Paging/src/main/org/hornetq/core/paging/impl/PageTransactionInfoImpl.java
branches/Branch_New_Paging/src/main/org/hornetq/core/server/impl/QueueImpl.java
Log:
tweaks
Modified: branches/Branch_New_Paging/src/main/org/hornetq/core/paging/cursor/impl/PageSubscriptionImpl.java
===================================================================
--- branches/Branch_New_Paging/src/main/org/hornetq/core/paging/cursor/impl/PageSubscriptionImpl.java 2010-11-12 20:24:00 UTC (rev 9883)
+++ branches/Branch_New_Paging/src/main/org/hornetq/core/paging/cursor/impl/PageSubscriptionImpl.java 2010-11-13 02:43:47 UTC (rev 9884)
@@ -209,8 +209,8 @@
{
if (entry.getKey() == lastAckedPosition.getPageNr())
{
- PageSubscriptionImpl.trace("We can't clear page " + entry.getKey() +
- " now since it's the current page");
+ // PageSubscriptionImpl.trace("We can't clear page " + entry.getKey() +
+ // " now since it's the current page");
}
else
{
@@ -1030,115 +1030,120 @@
/* (non-Javadoc)
* @see org.hornetq.core.paging.cursor.PageCursor#moveNext()
*/
- public synchronized PagedReference moveNext() throws Exception
+ public PagedReference moveNext() throws Exception
{
- boolean match = false;
+ synchronized (PageSubscriptionImpl.this)
+ {
+ boolean match = false;
- PagedReference message = null;
+ PagedReference message = null;
- PagePosition lastPosition = position;
- PagePosition tmpPosition = position;
+ PagePosition lastPosition = position;
+ PagePosition tmpPosition = position;
- do
- {
- synchronized (redeliveries)
+ do
{
- if (redeliveryIterator.hasNext())
+ synchronized (redeliveries)
{
- // There's a redelivery pending, we will get it out of that pool instead
- isredelivery = true;
- return getReference(redeliveryIterator.next());
+ if (redeliveryIterator.hasNext())
+ {
+ // There's a redelivery pending, we will get it out of that pool instead
+ isredelivery = true;
+ PagedReference redeliveredMsg = getReference(redeliveryIterator.next());
+
+ return redeliveredMsg;
+ }
+ else
+ {
+ isredelivery = false;
+ }
+
+ message = internalGetNext(tmpPosition);
}
- else
+
+ if (message == null)
{
- isredelivery = false;
+ break;
}
- message = internalGetNext(tmpPosition);
- }
+ tmpPosition = message.getPosition();
- if (message == null)
- {
- break;
- }
+ boolean valid = true;
+ boolean ignored = false;
- tmpPosition = message.getPosition();
+ // Validate the scenarios where the message should be considered not valid even to be considered
- boolean valid = true;
- boolean ignored = false;
+ // 1st... is it routed?
- // Validate the scenarios where the message should be considered not valid even to be considered
+ valid = routed(message.getPagedMessage());
+ if (!valid)
+ ignored = true;
- // 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)
+ // 2nd ... if TX, is it committed?
+ if (valid && message.getPagedMessage().getTransactionID() != 0)
{
- log.warn("Couldn't locate page transaction " + message.getPagedMessage().getTransactionID() +
- ", ignoring message on position " +
- message.getPosition());
- valid = false;
- ignored = true;
+ 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;
+ }
+ }
}
- else
+
+ // 3rd... was it previously removed?
+ if (valid)
{
- if (tx.deliverAfterCommit(PageSubscriptionImpl.this, message.getPosition()))
+ // 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;
- 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()))
+ if (!ignored)
{
- valid = false;
+ position = message.getPosition();
}
- }
- if (!ignored)
- {
- position = message.getPosition();
- }
+ if (valid)
+ {
+ match = match(message.getMessage());
- if (valid)
- {
- match = match(message.getMessage());
-
- if (!match)
+ if (!match)
+ {
+ processACK(message.getPosition());
+ }
+ }
+ else if (ignored)
{
- processACK(message.getPosition());
+ positionIgnored(message.getPosition());
}
}
- else if (ignored)
+ while (message != null && !match);
+
+ if (message != null)
{
- positionIgnored(message.getPosition());
+ lastOperation = lastPosition;
}
- }
- while (message != null && !match);
- if (message != null)
- {
- lastOperation = lastPosition;
+ return message;
}
-
- return message;
}
/** QueueImpl::deliver could be calling hasNext while QueueImpl.depage could be using next and hasNext as well.
Modified: branches/Branch_New_Paging/src/main/org/hornetq/core/paging/impl/PageTransactionInfoImpl.java
===================================================================
--- branches/Branch_New_Paging/src/main/org/hornetq/core/paging/impl/PageTransactionInfoImpl.java 2010-11-12 20:24:00 UTC (rev 9883)
+++ branches/Branch_New_Paging/src/main/org/hornetq/core/paging/impl/PageTransactionInfoImpl.java 2010-11-13 02:43:47 UTC (rev 9884)
@@ -51,6 +51,8 @@
private volatile long recordID = -1;
private volatile boolean committed = false;
+
+ private volatile boolean useRedelivery = false;
private volatile boolean rolledback = false;
@@ -237,6 +239,12 @@
*/
public synchronized boolean deliverAfterCommit(PageSubscription cursor, PagePosition cursorPos)
{
+ if (committed && useRedelivery)
+ {
+ cursor.redeliver(cursorPos);
+ return true;
+ }
+ else
if (committed)
{
return false;
@@ -249,6 +257,7 @@
}
else
{
+ useRedelivery = true;
if (lateDeliveries == null)
{
lateDeliveries = new LinkedList<Pair<PageSubscription, PagePosition>>();
Modified: branches/Branch_New_Paging/src/main/org/hornetq/core/server/impl/QueueImpl.java
===================================================================
--- branches/Branch_New_Paging/src/main/org/hornetq/core/server/impl/QueueImpl.java 2010-11-12 20:24:00 UTC (rev 9883)
+++ branches/Branch_New_Paging/src/main/org/hornetq/core/server/impl/QueueImpl.java 2010-11-13 02:43:47 UTC (rev 9884)
@@ -1273,7 +1273,7 @@
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());
+ //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())
@@ -1283,12 +1283,12 @@
pageIterator.remove();
}
- System.out.println("Depaged " + nmessages);
+ //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());
- }
+// else
+// {
+// System.out.println("Depaging not being done now.. there are msgRef = " + messageReferences.size() + " scheduled = " + getScheduledCount() + " concurrentQueue.size() = " + concurrentQueue.size());
+// }
deliverAsync();
}
14 years, 1 month