JBoss hornetq SVN: r8566 - trunk/src/config/common.
by do-not-reply@jboss.org
Author: timfox
Date: 2009-12-04 14:59:07 -0500 (Fri, 04 Dec 2009)
New Revision: 8566
Modified:
trunk/src/config/common/hornetq-version.properties
Log:
updated version
Modified: trunk/src/config/common/hornetq-version.properties
===================================================================
--- trunk/src/config/common/hornetq-version.properties 2009-12-04 19:34:12 UTC (rev 8565)
+++ trunk/src/config/common/hornetq-version.properties 2009-12-04 19:59:07 UTC (rev 8566)
@@ -1,8 +1,8 @@
-hornetq.version.versionName=hornet-baby
+hornetq.version.versionName=stinger
hornetq.version.majorVersion=2
hornetq.version.minorVersion=0
hornetq.version.microVersion=0
-hornetq.version.incrementingVersion=108
-hornetq.version.versionSuffix=BETA5
-hornetq.version.versionTag=beta5
+hornetq.version.incrementingVersion=109
+hornetq.version.versionSuffix=CR1
+hornetq.version.versionTag=CR1
hornetq.netty.version=(a)NETTY.VERSION@
15 years, 1 month
JBoss hornetq SVN: r8565 - trunk/docs/user-manual/en.
by do-not-reply@jboss.org
Author: timfox
Date: 2009-12-04 14:34:12 -0500 (Fri, 04 Dec 2009)
New Revision: 8565
Modified:
trunk/docs/user-manual/en/perf-tuning.xml
trunk/docs/user-manual/en/persistence.xml
Log:
more docs changes
Modified: trunk/docs/user-manual/en/perf-tuning.xml
===================================================================
--- trunk/docs/user-manual/en/perf-tuning.xml 2009-12-04 17:37:55 UTC (rev 8564)
+++ trunk/docs/user-manual/en/perf-tuning.xml 2009-12-04 19:34:12 UTC (rev 8565)
@@ -20,17 +20,17 @@
<title>Performance Tuning</title>
<para>In this chapter we'll discuss how to tune HornetQ for optimum performance.</para>
<section>
- <title>Tuning the journal</title>
+ <title>Tuning persistence</title>
<itemizedlist>
<listitem>
- <para>Put the journal on its own physical volume. If the disk is shared with other
- processes e.g. transaction co-ordinator, database or other journals which are
- also reading and writing from it, then this may greatly reduce performance since
- the disk head may be skipping all over the place between the different files.
- One of the advantages of an append only journal is that disk head movement is
- minimised - this advantage is destroyed if the disk is shared. If you're using
- paging or large messages make sure they're ideally put on separate volumes
- too.</para>
+ <para>Put the message journal on its own physical volume. If the disk is shared with
+ other processes e.g. transaction co-ordinator, database or other journals which
+ are also reading and writing from it, then this may greatly reduce performance
+ since the disk head may be skipping all over the place between the different
+ files. One of the advantages of an append only journal is that disk head
+ movement is minimised - this advantage is destroyed if the disk is shared. If
+ you're using paging or large messages make sure they're ideally put on separate
+ volumes too.</para>
</listitem>
<listitem>
<para>Minimum number of journal files. Set <literal>journal-min-files</literal> to a
@@ -49,16 +49,14 @@
will scale better than Java NIO.</para>
</listitem>
<listitem>
- <para><literal>journal-flush-on-sync</literal>. If you don't have many producers
- in your system you may consider setting journal-flush-on-sync to true.
- HornetQ by default is optimized by the case where you have many producers. We
- try to combine multiple writes in a single OS operation. However if that's not
- your case setting this option to true will give you a performance boost.</para>
- <para>On the other hand when you have multiple producers, keeping <literal
- >journal-flush-on-sync</literal> set to false. This will make your
- system flush multiple syncs in a single OS call making your system scale much
- better.</para>
+ <para>Tune <literal>journal-buffer-timeout</literal>. The timeout can be increased
+ to increase throughput at the expense of latency.</para>
</listitem>
+ <listitem>
+ <para>If you're running AIO you might be able to get some better performance by
+ increasing <literal>journal-max-io</literal>. DO NOT change this parameter if
+ you are running NIO.</para>
+ </listitem>
</itemizedlist>
</section>
<section>
@@ -141,6 +139,23 @@
information.</para>
</listitem>
<listitem>
+ <para>Sync non transactional lazily. Setting <literal
+ >journal-sync-non-transactional</literal> to <literal>false</literal> in
+ <literal>hornetq-configuration.xml</literal> can give you better
+ non-transactional persistent performance at the expense of some possibility of
+ loss of persistent messages on failure. See <xref linkend="send-guarantees"/>
+ for more information.</para>
+ </listitem>
+ <listitem>
+ <para>Send messages non blocking. Setting <literal
+ >block-on-persistent-send</literal> and <literal
+ >block-on-non-persistent-send</literal> to <literal>false</literal> in
+ <literal>hornetq-jms.xml</literal> (if you're using JMS and JNDI) or
+ directly on the ClientSessionFactory. This means you don't have to wait a whole
+ network round trip for every message sent. See <xref linkend="send-guarantees"/>
+ for more information.</para>
+ </listitem>
+ <listitem>
<para>Use the core API not JMS. Using the JMS API you will have slightly lower
performance than using the core API, since all JMS operations need to be
translated into core operations before the server can handle them.</para>
@@ -154,9 +169,11 @@
<para>Enable <ulink url="http://en.wikipedia.org/wiki/Nagle's_algorithm">Nagle's
algorithm</ulink>. If you are sending many small messages, such that more
than one can fit in a single IP packet thus providing better performance. This
- is done by setting <literal>tcpnodelay</literal> to false
- with the Netty transports. See <xref linkend="configuring-transports"/> for more
- information on this. </para>
+ is done by setting <literal>tcpnodelay</literal> to false with the Netty
+ transports. See <xref linkend="configuring-transports"/> for more information on
+ this. </para>
+ <para>Enabling Nagle's algorithm can make a very big difference in performance and
+ is highly recommended if you're sending a lot of asynchronous traffice.</para>
</listitem>
<listitem>
<para>TCP buffer sizes. If you have a fast network and fast machines you may get a
@@ -201,13 +218,15 @@
size and number of your messages. Use the JVM arguments <literal>-Xms</literal>
and <literal>-Xmx</literal> to set server available RAM. We recommend setting
them to the same high value.</para>
- <para>HornetQ will regularly sample JVM memory and reports if the available memory is below
- a configurable threshold. Use this information to properly set JVM memory and paging.
- The sample is disabled by default. To enabled it, configure the sample frequency by setting <literal>memory-measure-interval</literal>
- in <literal>hornetq-configuration.xml</literal> (in milliseconds).
- When the available memory goes below the configured threshold, a warning is logged.
- The threshold can be also configured by setting <literal>memory-warning-threshold</literal> in
- <literal>hornetq-configuration.xml</literal> (default is 25%).</para>
+ <para>HornetQ will regularly sample JVM memory and reports if the available memory
+ is below a configurable threshold. Use this information to properly set JVM
+ memory and paging. The sample is disabled by default. To enabled it, configure
+ the sample frequency by setting <literal>memory-measure-interval</literal> in
+ <literal>hornetq-configuration.xml</literal> (in milliseconds). When the
+ available memory goes below the configured threshold, a warning is logged. The
+ threshold can be also configured by setting <literal
+ >memory-warning-threshold</literal> in <literal
+ >hornetq-configuration.xml</literal> (default is 25%).</para>
</listitem>
<listitem>
<para>Aggressive options. Different JVMs provide different sets of JVM tuning
@@ -263,10 +282,11 @@
Instead the temporary queue should be re-used for many requests.</para>
</listitem>
<listitem>
- <para>Don't use Message-Driven Beans for the sake of it. As soon as you start using MDBs you are greatly
- increasing the codepath for each message received compared to a straightforward message consumer, since a lot of
- extra application server code is executed. Ask yourself
- do you really need MDBs? Can you accomplish the same task using just a normal message consumer?</para>
+ <para>Don't use Message-Driven Beans for the sake of it. As soon as you start using
+ MDBs you are greatly increasing the codepath for each message received compared
+ to a straightforward message consumer, since a lot of extra application server
+ code is executed. Ask yourself do you really need MDBs? Can you accomplish the
+ same task using just a normal message consumer?</para>
</listitem>
</itemizedlist>
</section>
Modified: trunk/docs/user-manual/en/persistence.xml
===================================================================
--- trunk/docs/user-manual/en/persistence.xml 2009-12-04 17:37:55 UTC (rev 8564)
+++ trunk/docs/user-manual/en/persistence.xml 2009-12-04 19:34:12 UTC (rev 8565)
@@ -20,11 +20,10 @@
<title>Persistence</title>
<para>In this chapter we will describe how persistence works with HornetQ and how to configure
it.</para>
- <para>HornetQ ships with a high performance journal. This journal has been implemented by the
- HornetQ team with a view to providing high performance in a messaging system. Since HornetQ
- handles its own persistence, rather than relying on a database or other 3rd party
- persistence engine, we have been able to tune the journal to gain optimal performance for
- the persistence of messages and transactions.</para>
+ <para>HornetQ ships with a high performance journal. Since HornetQ handles its own persistence,
+ rather than relying on a database or other 3rd party persistence engine, we have been able
+ to tune the journal to gain optimal performance for the persistence of messages and
+ transactions.</para>
<para>A HornetQ journal is an <emphasis>append only</emphasis> journal. It consists of a set of
files on disk. Each file is pre-created to a fixed size and initially filled with padding.
As operations are performed on the server, e.g. add message, update message, delete message,
@@ -61,13 +60,13 @@
<para>Linux Asynchronous IO</para>
<para>The second implementation uses a thin native code wrapper to talk to the Linux
asynchronous IO library (AIO). In a highly concurrent environment, AIO can provide
- better overall persistent throughput since it does not require each individual
- transaction boundary to be synced to disk. Most disks can only support a limited
- number of syncs per second, so a syncing approach does not scale well when the
- number of concurrent transactions needed to be committed grows too large. With AIO,
- HornetQ will be called back when the data has made it to disk, allowing us to avoid
- explicit syncs altogether and simply send back confirmation of completion when AIO
- informs us that the data has been persisted.</para>
+ better overall persistent throughput since it does not require explicit syncs to
+ flush operating system buffers to disk. Most disks can only support a limited number
+ of syncs per second, so a syncing approach does not scale well when the number of
+ concurrent transactions needed to be committed grows too large. With AIO, HornetQ
+ will be called back when the data has made it to disk, allowing us to avoid explicit
+ syncs altogether and simply send back confirmation of completion when AIO informs us
+ that the data has been persisted.</para>
<para>The AIO journal is only available when running Linux kernel 2.6 or later and after
having installed libaio (if it's not already installed). For instructions on how to
install libaio please see <xref linkend="installing-aio"/>.</para>
@@ -156,15 +155,15 @@
</listitem>
<listitem id="configuring.message.journal.journal-sync-transactional">
<para><literal>journal-sync-transactional</literal></para>
- <para>If this is set to true then HornetQ will wait for all transaction data to be
- persisted to disk on a commit before sending a commit response OK back to the
- client. The default value is <literal>true</literal>.</para>
+ <para>If this is set to true then HornetQ will make sure all transaction data is
+ flushed to disk on transaction boundaries (commit, prepare and rollback). The
+ default value is <literal>true</literal>.</para>
</listitem>
<listitem id="configuring.message.journal.journal-sync-non-transactional">
<para><literal>journal-sync-non-transactional</literal></para>
- <para>If this is set to true then HornetQ will wait for any non transactional data
- to be persisted to disk on a send before sending the response back to the
- client. The default value for this is <literal>false</literal>.</para>
+ <para>If this is set to true then HornetQ will make sure non transactional message
+ data (sends and acknowledgements) are flushed to disk each time. The default
+ value for this is <literal>true</literal>.</para>
</listitem>
<listitem id="configuring.message.journal.journal-file-size">
<para><literal>journal-file-size</literal></para>
@@ -185,45 +184,38 @@
</listitem>
<listitem id="configuring.message.journal.journal-max-io">
<para><literal>journal-max-io</literal></para>
- <para>When using an AIO journal, write requests are queued up before being submitted
- to AIO for execution. Then when AIO has completed them it calls HornetQ back.
+ <para>Write requests are queued up before being submitted to the system execution.
This parameter controls the maximum number of write requests that can be in the
- AIO queue at any one time. If the queue becomes full then writes will block
- until space is freed up. This parameter has no meaning when using the NIO
- journal.</para>
+ IO queue at any one time. If the queue becomes full then writes will block until
+ space is freed up. </para>
+ <para>When using NIO, this value should always be equal to <literal
+ >1</literal></para>
+ <para>When using AIO, the default should be <literal>500</literal>.</para>
+ <para>The system maintains different defaults for this parameter depening on whether
+ it's NIO or AIO (default for NIO is 1, default for AIO is 500)</para>
<para>There is a limit and the total max AIO can't be higher than what is configured
at the OS level (/proc/sys/fs/aio-max-nr) usually at 65536.</para>
- <para>The default value for this is <literal>500</literal>. </para>
</listitem>
<listitem id="configuring.message.journal.journal-buffer-timeout">
<para><literal>journal-buffer-timeout</literal></para>
- <para>Flush period on the internal AIO timed buffer, configured in nano seconds. For
- performance reasons we buffer data before submitting it to the kernel in a
- single batch. This parameter determines the maximum amount of time to wait
- before flushing the buffer, if it does not get full by itself in that
- time.</para>
- <para>The default value for this paramater is <literal>20000</literal> nano seconds
- (i.e. 20 microseconds). </para>
+ <para>Instead of flushing on every write that requires a flush, we maintain an
+ internal buffer, and flush the entire buffer either when it is full, or when a
+ timeout expires, whichever is sooner. This is used for both NIO and AIO and
+ allows the system to scale better with many concurrent writes that require
+ flushing.</para>
+ <para>This parameter controls the timeout at which the buffer will be flushed if it
+ hasn't filled already. AIO can typically cope with a higher flush rate than NIO,
+ so the system maintains different defaults for both NIO and AIO (default for NIO
+ is 3333333 nanoseconds - 300 times per second, default for AIO is 500000
+ nanoseconds - ie. 2000 times per second).</para>
+ <para>By increasing the timeout, you may be able to increase system throughput at
+ the expense of latency, the default parameters are chosen to give a reasonable
+ balance between throughput and latency.</para>
</listitem>
- <listitem id="configuring.message.journal.journal-flush-on-sync">
- <para><literal>journal-flush-on-sync</literal></para>
- <para>If this is set to true, the internal buffers are flushed right away when a
- sync request is performed. Sync requests are performed on transactions if
- <literal>journal-sync-transactional</literal> is true, or on sending regular
- messages if <literal>journalsync-non-transactional</literal> is true.</para>
- <para>HornetQ was made to scale up to hundreds of producers. We try to use most of
- the hardware resources by scheduling multiple writes and syncs in a single OS
- call.</para>
- <para>However in some use cases it may be better to not wait any data and just flush
- and write to the OS right away. For example if you have a single producer
- writing small transactions. On this case it would be better to always
- flush-on-sync.</para>
- <para>The default value for this parameter is <literal>false</literal>. </para>
- </listitem>
<listitem id="configuring.message.journal.journal-buffer-size">
<para><literal>journal-buffer-size</literal></para>
<para>The size of the timed buffer on AIO. The default value is <literal
- >128KiB</literal>.</para>
+ >490KiB</literal>.</para>
</listitem>
<listitem id="configuring.message.journal.journal-compact-min-files">
<para><literal>journal-compact-min-files</literal></para>
@@ -242,6 +234,33 @@
</listitem>
</itemizedlist>
</section>
+ <section id="disk-write-cache">
+ <title>An important note on disabling disk write cache.</title>
+ <warning>
+ <para>Most disks contain hardware write caches. A write cache can increase the apparent
+ performance of the disk because writes just go into the cache and are then lazily
+ written to the disk later. </para>
+ <para>This happens irrespective of whether you have executed a fsync() from the operating
+ system or correctly synced data from inside a Java program!</para>
+ <para>By default many systems ship with disk write cache enabled. This means that even after
+ syncing from the operating system there is no guarantee the data has actually made it to
+ disk, so if a failure occurs, critical data can be lost.</para>
+ <para>Some more expensive disks have non volatile or battery backed write caches which won't
+ necessarily lose data on event of failure, but you need to test them!</para>
+ <para>If your disk does not have an expensive non volatile or battery backed cache and it's
+ not part of some kind of redundant array, and you value your data integrity you need to
+ make sure disk write cache is disabled.</para>
+ <para>Be aware that disabling disk write cache can give you a nasty shock performance wise.
+ If you've been used to using disks with write cache enabled in their default setting,
+ unaware that your data integrity could be compromised, then disabling it will give you
+ an idea of how fast your disk can perform when acting really reliably.</para>
+ <para>On Linux you can inspect and/or change your disk's write cache settings using the
+ tools <literal>hdparm</literal> (for IDE disks) or <literal>sdparm</literal> or <literal
+ >sginfo</literal> (for SDSI/SATA disks)</para>
+ <para>On Windows you can check / change the setting by right clicking on the disk and
+ clicking properties.</para>
+ </warning>
+ </section>
<section id="installing-aio">
<title>Installing AIO</title>
<para>The Java NIO journal gives great performance, but If you are running HornetQ using
15 years, 1 month
JBoss hornetq SVN: r8564 - trunk/tests/src/org/hornetq/tests/stress/journal.
by do-not-reply@jboss.org
Author: clebert.suconic(a)jboss.com
Date: 2009-12-04 12:37:55 -0500 (Fri, 04 Dec 2009)
New Revision: 8564
Modified:
trunk/tests/src/org/hornetq/tests/stress/journal/MultiThreadConsumerStressTest.java
Log:
Fixing test
Modified: trunk/tests/src/org/hornetq/tests/stress/journal/MultiThreadConsumerStressTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/stress/journal/MultiThreadConsumerStressTest.java 2009-12-04 17:29:30 UTC (rev 8563)
+++ trunk/tests/src/org/hornetq/tests/stress/journal/MultiThreadConsumerStressTest.java 2009-12-04 17:37:55 UTC (rev 8564)
@@ -69,6 +69,18 @@
int consumeMessage = (int) (produceMessage * 0.9);
int commitIntervalConsume = 100;
+ ClientSession session = sf.createSession(false, false);
+ session.createQueue("compact", "compact-queue", true);
+
+ ClientProducer producer = session.createProducer("compact");
+
+ for (int i = 0 ; i < 100; i++)
+ {
+ producer.send(session.createClientMessage(true));
+ }
+
+ session.commit();
+
// Number of messages expected to be received after restart
int numberOfMessagesExpected = (produceMessage - consumeMessage) * numberOfConsumers;
@@ -123,9 +135,9 @@
ClientMessage msg = consumer.receive(5000);
assertNotNull(msg);
- if (i % 100 == 0)
+ if (i % 1000 == 0)
{
- System.out.println("Received #" + i + " on thread after start");
+ System.out.println("Received #" + i + " on thread before end");
}
msg.acknowledge();
}
@@ -165,7 +177,7 @@
config.setJournalFileSize(ConfigurationImpl.DEFAULT_JOURNAL_FILE_SIZE);
config.setJournalMinFiles(ConfigurationImpl.DEFAULT_JOURNAL_MIN_FILES);
- config.setJournalCompactMinFiles(0);
+ config.setJournalCompactMinFiles(2);
config.setJournalCompactPercentage(50);
server = createServer(true, config);
@@ -254,9 +266,9 @@
{
session.commit();
}
- if (i % 100 == 0)
+ if (i % 1000 == 0)
{
- System.out.println(Thread.currentThread().getName() + "::received #" + i);
+ //System.out.println(Thread.currentThread().getName() + "::received #" + i);
}
ClientMessage msg = session.createClientMessage(true);
prod.send(msg);
@@ -314,9 +326,9 @@
{
session.commit();
}
- if (i % 100 == 0)
+ if (i % 1000 == 0)
{
- System.out.println(Thread.currentThread().getName() + "::sent #" + i);
+ //System.out.println(Thread.currentThread().getName() + "::sent #" + i);
}
}
15 years, 1 month
JBoss hornetq SVN: r8563 - trunk/docs/user-manual/en.
by do-not-reply@jboss.org
Author: timfox
Date: 2009-12-04 12:29:30 -0500 (Fri, 04 Dec 2009)
New Revision: 8563
Modified:
trunk/docs/user-manual/en/send-guarantees.xml
Log:
more docs changes
Modified: trunk/docs/user-manual/en/send-guarantees.xml
===================================================================
--- trunk/docs/user-manual/en/send-guarantees.xml 2009-12-04 17:25:32 UTC (rev 8562)
+++ trunk/docs/user-manual/en/send-guarantees.xml 2009-12-04 17:29:30 UTC (rev 8563)
@@ -139,7 +139,8 @@
back an acknowledgment of the send asynchronously, and some time later you are
informed at the client side by HornetQ calling your handler's <literal
>sendAcknowledged(ClientMessage message)</literal> method, passing in a
- reference to the message that was sent.</para>
+ reference to the message that was sent.</para>
+ <para>To enable asynchronous send acknowledgements you must make sure <literal>confirmation-window-size</literal> is set to a positive integer value, e.g. 10MiB</para>
<para>Please see <xref linkend="asynchronous-send-acknowledgements-example"/> for a full
working example.</para>
</section>
15 years, 1 month
JBoss hornetq SVN: r8562 - trunk/docs/user-manual/en.
by do-not-reply@jboss.org
Author: timfox
Date: 2009-12-04 12:25:32 -0500 (Fri, 04 Dec 2009)
New Revision: 8562
Modified:
trunk/docs/user-manual/en/paging.xml
trunk/docs/user-manual/en/queue-attributes.xml
trunk/docs/user-manual/en/send-guarantees.xml
Log:
more docs changes
Modified: trunk/docs/user-manual/en/paging.xml
===================================================================
--- trunk/docs/user-manual/en/paging.xml 2009-12-04 17:12:44 UTC (rev 8561)
+++ trunk/docs/user-manual/en/paging.xml 2009-12-04 17:25:32 UTC (rev 8562)
@@ -85,7 +85,7 @@
<address-setting match="jms.someaddress">
<max-size-bytes>104857600</max-size-bytes>
<page-size-bytes>10485760</page-size-bytes>
- <drop-messages-when-full>false</drop-messages-when-full>
+ <address-full-policy>PAGE</address-full-policy>
</address-setting>
</address-settings>
</programlisting>
@@ -117,11 +117,11 @@
<entry>10MiB (10 * 1024 * 1024 bytes)</entry>
</row>
<row>
- <entry><literal>drop-messages-when-full</literal></entry>
- <entry>if true, messages are dropped instead of paged when <literal
- >used-memory</literal> is greater than <literal
- >max-size</literal></entry>
- <entry>false</entry>
+ <entry><literal>address-full-message-policy</literal></entry>
+ <entry>This must be set to PAGE for paging to enable. If the value is PAGE then further messages will be paged to disk.
+ If the value is DROP then further messages will be silently dropped.
+ If the value is BLOCK then client message producers will block when they try and send further messages.</entry>
+ <entry>PAGE</entry>
</row>
</tbody>
</tgroup>
Modified: trunk/docs/user-manual/en/queue-attributes.xml
===================================================================
--- trunk/docs/user-manual/en/queue-attributes.xml 2009-12-04 17:12:44 UTC (rev 8561)
+++ trunk/docs/user-manual/en/queue-attributes.xml 2009-12-04 17:25:32 UTC (rev 8562)
@@ -100,6 +100,7 @@
<page-size-bytes>20000</page-size-bytes>
<redistribution-delay>0</redistribution-delay>
<send-to-dla-on-no-route>true</send-to-dla-on-no-route>
+ <address-full-policy>PAGE</address-full-policy>
</address-setting>
</address-settings></programlisting>
<para>The idea with address settings, is you can provide a block of settings which will be
@@ -131,5 +132,14 @@
for example, there might be no queues bound to that address, or none of the queues have filters that match, then normally that message
would be discarded. However if this parameter is set to true for that address, if the message is not routed to any queues it will instead
be sent to the dead letter address (DLA) for that address, if it exists.</para>
+ <para><literal>address-full-policy</literal>. This attribute can have one of the following values: PAGE, DROP or BLOCK and determines what happens when
+ an address where <literal>max-size-bytes</literal> is specified becomes full. The default value is PAGE. If the value is PAGE then further messages will be paged to disk.
+ If the value is DROP then further messages will be silently dropped.
+ If the value is BLOCK then client message producers will block when they try and send further messages.
+
+ See the following chapters for more info <xref linkend="flow-control"/>, <xref linkend="paging"/>.
+ </para>
+
+
</section>
</chapter>
Modified: trunk/docs/user-manual/en/send-guarantees.xml
===================================================================
--- trunk/docs/user-manual/en/send-guarantees.xml 2009-12-04 17:12:44 UTC (rev 8561)
+++ trunk/docs/user-manual/en/send-guarantees.xml 2009-12-04 17:25:32 UTC (rev 8562)
@@ -127,6 +127,8 @@
the network RTT, but is limited by the network bandwidth. Consequently better throughput
can be achieved than is possible using a blocking approach, while at the same time
having absolute guarantees that messages have successfully reached the server.</para>
+ <para>The window size for send acknowledgements is determined by the confirmation-window-size parameter on
+ the connection factory or client session factory. Please see <xref linkend="client-reconnection"/> for more info on this.</para>
<section>
<title>Asynchronous Send Acknowledgements</title>
<para>To use the feature using the core API, you implement the interface <literal
15 years, 1 month
JBoss hornetq SVN: r8561 - trunk/docs/user-manual/en.
by do-not-reply@jboss.org
Author: timfox
Date: 2009-12-04 12:12:44 -0500 (Fri, 04 Dec 2009)
New Revision: 8561
Modified:
trunk/docs/user-manual/en/core-bridges.xml
Log:
more docs changes
Modified: trunk/docs/user-manual/en/core-bridges.xml
===================================================================
--- trunk/docs/user-manual/en/core-bridges.xml 2009-12-04 16:53:46 UTC (rev 8560)
+++ trunk/docs/user-manual/en/core-bridges.xml 2009-12-04 17:12:44 UTC (rev 8561)
@@ -59,6 +59,7 @@
<reconnect-attempts>-1</reconnect-attempts>
<failover-on-server-shutdown>false</failover-on-server-shutdown>
<use-duplicate-detection>true</use-duplicate-detection>
+ <confirmation-window-size>10000000</confirmation-window-size>
<connector-ref connector-name="remote-connector"
backup-connector-name="backup-remote-connector"/>
</bridge>
@@ -167,6 +168,17 @@
<para>The default value for this parameter is <literal>true</literal>.</para>
</listitem>
<listitem>
+ <para><literal>confirmation-window-size</literal>. This optional parameter determines
+ the <literal>confirmation-window-size</literal> to use for the connection used to forward messages to the target node.
+ This attribute is described in section <xref linkend="client-reconnection"/></para>
+ <para>
+ <warning>When using the bridge to forward messages from a queue which has a max-size-bytes set it's important
+ that confirmation-window-size is less than or equal to <literal>max-size-bytes</literal> to prevent the flow of messages from ceasing.
+ </warning>
+ </para>
+
+ </listitem>
+ <listitem>
<para><literal>connector-ref</literal>. This mandatory parameter determines which
<emphasis>connector</emphasis> pair the bridge will use to actually make the
connection to the target server.</para>
15 years, 1 month
JBoss hornetq SVN: r8560 - in trunk/docs/user-manual: en and 1 other directory.
by do-not-reply@jboss.org
Author: timfox
Date: 2009-12-04 11:53:46 -0500 (Fri, 04 Dec 2009)
New Revision: 8560
Removed:
trunk/docs/user-manual/en/command-buffering.xml
Modified:
trunk/docs/user-manual/en/client-reconnection.xml
trunk/docs/user-manual/en/configuration-index.xml
trunk/docs/user-manual/en/master.xml
trunk/docs/user-manual/user-manual.xpr
Log:
more docs changes
Modified: trunk/docs/user-manual/en/client-reconnection.xml
===================================================================
--- trunk/docs/user-manual/en/client-reconnection.xml 2009-12-04 16:33:18 UTC (rev 8559)
+++ trunk/docs/user-manual/en/client-reconnection.xml 2009-12-04 16:53:46 UTC (rev 8560)
@@ -17,69 +17,105 @@
<!-- permitted by applicable law. -->
<!-- ============================================================================= -->
<chapter id="client-reconnection">
- <title>Client Reconnection</title>
+ <title>Client Reconnection and Session Reattachment</title>
<para>HornetQ clients can be configured to automatically reconnect or re-attach to the server in
the event that a failure is detected in the connection between the client and the server. </para>
- <para>If the failure was due to some transient failure such as a temporary network failure, and
- the target server was not restarted, then the sessions will still be existent on the server,
- asssuming the client hasn't been disconnected for more than connection-ttl.</para>
- <para>In this scenario, HornetQ will automatically re-attach the client sessions to the server
- sessions when the connection reconnects. This is done 100% transparently and the client can
- continue exactly as if nothing had happened.</para>
- <para>Alternatively, the server might have actually been restarted after crashing or being
- stopped. In this case any sessions will no longer be existent on the server and it won't be
- possible to automatically re-attach to them.</para>
- <para>In this case, HornetQ will automatically reconnect the connection and recreate any
- sessions and consumers on the server corresponding to the sessions and consumers on the
- client. This process is exactly the same as what happens during failover onto a backup
- server.</para>
- <para>Please see the section on failover <xref linkend="ha.automatic.failover"/> to get a full
- understanding of how transacted and non-transacted sessions are reconnected during
- failover/reconnect.</para>
- <para>Client reconnection is also used internally by components such as core bridges to allow
- them to reconnect to their target servers.</para>
- <para>Client reconnection is configured using the following parameters:</para>
- <itemizedlist>
- <listitem>
- <para><literal>retry-interval</literal>. This optional parameter determines the period
- in milliseconds between subsequent reconnection attempts, if the connection to the
- target server has failed. The default value is <literal>2000</literal>
- milliseconds.</para>
- </listitem>
- <listitem>
- <para><literal>retry-interval-multiplier</literal>. This optional parameter determines
- determines a multiplier to apply to the time since the last retry to compute the
- time to the next retry.</para>
- <para>This allows you to implement an <emphasis>exponential backoff</emphasis> between
- retry attempts.</para>
- <para>Let's take an example:</para>
- <para>If we set <literal>retry-interval</literal> to <literal>1000</literal> ms and we
- set <literal>retry-interval-multiplier</literal> to <literal>2.0</literal>, then, if
- the first reconnect attempt fails, we will wait <literal>1000</literal> ms then
- <literal>2000</literal> ms then <literal>4000</literal> ms between subsequent
- reconnection attempts.</para>
- <para>The default value is <literal>1.0</literal> meaning each reconnect attempt is
- spaced at equal intervals.</para>
- </listitem>
- <listitem>
- <para><literal>max-retry-interval</literal>. This optional parameter determines the
- maximum retry interval that will be used. When setting <literal
- >retry-interval-multiplier</literal> it would otherwise be possible that
- subsequent retries exponentially increase to ridiculously large values. By setting
- this parameter you can set an upper limit on that value. The default value is
- <literal>2000</literal> milliseconds.</para>
- </listitem>
- <listitem>
- <para><literal>reconnect-attempts</literal>. This optional parameter determines the
- total number of reconnect attempts to make before giving up and shutting down. A
- value of <literal>-1</literal> signifies an unlimited number of attempts. The
- default value is <literal>0</literal>.</para>
- </listitem>
- </itemizedlist>
- <para>If you're using JMS, and you're using the JMS Service on the server to load your JMS
- connection factory instances directly into JNDI, then you can specify these parameters in
- the xml configuration in <literal>hornetq-jms.xml</literal>, for example:</para>
- <programlisting>
+ <section>
+ <title>100% Transparent session re-attachment</title>
+ <para>If the failure was due to some transient failure such as a temporary network failure,
+ and the target server was not restarted, then the sessions will still be existent on the
+ server, asssuming the client hasn't been disconnected for more than connection-ttl <xref
+ linkend="connection-ttl"/>.</para>
+ <para>In this scenario, HornetQ will automatically re-attach the client sessions to the
+ server sessions when the connection reconnects. This is done 100% transparently and the
+ client can continue exactly as if nothing had happened.</para>
+ <para>The way this works is as follows:</para>
+ <para>As HornetQ clients send commands to their servers they store each sent command in an
+ in-memory buffer. In the case that connection failure occurs and the client subsequently
+ reattaches to the same server, as part of the reattachment protocol the server informs
+ the client during reattachment with the id of the last command it successfully received
+ from that client.</para>
+ <para>If the client has sent more commands than were received before failover it can replay
+ any sent commands from its buffer so that the client and server can reconcile their
+ states.</para>
+ <para>The size of this buffer is configured by the <literal>ConfirmationWindowSize</literal>
+ parameter, when the server has received <literal>ConfirmationWindowSize</literal> bytes
+ of commands and processed them it will send back a command confirmation to the client,
+ and the client can then free up space in the buffer.</para>
+ <para>If you are using JMS and you're using the JMS service on the server to load your JMS
+ connection factory instances into JNDI then this parameter can be configured in <literal
+ >hornetq-jms.xml</literal> using the element <literal
+ >confirmation-window-size</literal> a. If you're using JMS but not using JNDI then
+ you can set these values directly on the <literal>HornetQConnectionFactory</literal>
+ instance using the appropriate setter method.</para>
+ <para>If you're using core you can set these values directly on the <literal
+ >ClientSessionFactory</literal> instance using the appropriate setter method.</para>
+ <para>The window is specified in bytes, and has a default value of <literal
+ >1MiB</literal>.</para>
+ <para>Setting this parameter to <literal>-1</literal> disables any buffering and prevents
+ any re-attachment from occurring, forcing reconnect instead. The default value for this
+ parameter is <literal>-1</literal>.</para>
+ </section>
+ <section>
+ <title>Session reconnection</title>
+ <para>Alternatively, the server might have actually been restarted after crashing or being
+ stopped. In this case any sessions will no longer be existent on the server and it won't
+ be possible to 100% transparently re-attach to them.</para>
+ <para>In this case, HornetQ will automatically reconnect the connection and <emphasis
+ role="italic">recreate</emphasis> any sessions and consumers on the server
+ corresponding to the sessions and consumers on the client. This process is exactly the
+ same as what happens during failover onto a backup server.</para>
+ <para>Client reconnection is also used internally by components such as core bridges to
+ allow them to reconnect to their target servers.</para>
+ <para>Please see the section on failover <xref linkend="ha.automatic.failover"/> to get a
+ full understanding of how transacted and non-transacted sessions are reconnected during
+ failover/reconnect and what you need to do to maintain <emphasis role="italic">once and
+ only once </emphasis>delivery guarantees.</para>
+ </section>
+ <section>
+ <title>Configuring reconnection/reattachment attributes</title>
+ <para>Client reconnection is configured using the following parameters:</para>
+ <itemizedlist>
+ <listitem>
+ <para><literal>retry-interval</literal>. This optional parameter determines the
+ period in milliseconds between subsequent reconnection attempts, if the
+ connection to the target server has failed. The default value is <literal
+ >2000</literal> milliseconds.</para>
+ </listitem>
+ <listitem>
+ <para><literal>retry-interval-multiplier</literal>. This optional parameter
+ determines determines a multiplier to apply to the time since the last retry to
+ compute the time to the next retry.</para>
+ <para>This allows you to implement an <emphasis>exponential backoff</emphasis>
+ between retry attempts.</para>
+ <para>Let's take an example:</para>
+ <para>If we set <literal>retry-interval</literal> to <literal>1000</literal> ms and
+ we set <literal>retry-interval-multiplier</literal> to <literal>2.0</literal>,
+ then, if the first reconnect attempt fails, we will wait <literal>1000</literal>
+ ms then <literal>2000</literal> ms then <literal>4000</literal> ms between
+ subsequent reconnection attempts.</para>
+ <para>The default value is <literal>1.0</literal> meaning each reconnect attempt is
+ spaced at equal intervals.</para>
+ </listitem>
+ <listitem>
+ <para><literal>max-retry-interval</literal>. This optional parameter determines the
+ maximum retry interval that will be used. When setting <literal
+ >retry-interval-multiplier</literal> it would otherwise be possible that
+ subsequent retries exponentially increase to ridiculously large values. By
+ setting this parameter you can set an upper limit on that value. The default
+ value is <literal>2000</literal> milliseconds.</para>
+ </listitem>
+ <listitem>
+ <para><literal>reconnect-attempts</literal>. This optional parameter determines the
+ total number of reconnect attempts to make before giving up and shutting down. A
+ value of <literal>-1</literal> signifies an unlimited number of attempts. The
+ default value is <literal>0</literal>.</para>
+ </listitem>
+ </itemizedlist>
+ <para>If you're using JMS, and you're using the JMS Service on the server to load your JMS
+ connection factory instances directly into JNDI, then you can specify these parameters
+ in the xml configuration in <literal>hornetq-jms.xml</literal>, for example:</para>
+ <programlisting>
<connection-factory name="ConnectionFactory">
<connectors>
<connector-ref connector-name="netty"/>
@@ -94,23 +130,23 @@
<reconnect-attempts>1000</reconnect-attempts>
</connection-factory>
</programlisting>
- <para>If you're using JMS, but instantiating your JMS connection factory directly, you can
- specify the parameters using the appropriate setter methods on the <literal
- >HornetQConnectionFactory</literal> immediately after creating it.</para>
- <para>If you're using the core API and instantiating the <literal>ClientSessionFactory</literal>
- instance directly you can also specify the parameters using the appropriate setter methods
- on the <literal>ClientSessionFactory</literal> immediately after creating it.</para>
- <para>If your client does manage to reconnect but the session is no longer available on the
- server, for instance if the server has been restarted or it has timed out, then the client
- won't be able to re-attach, and any <literal>ExceptionListener</literal> or <literal
- >FailureListener</literal> instances registered on the connection or session will be
- called.</para>
+ <para>If you're using JMS, but instantiating your JMS connection factory directly, you can
+ specify the parameters using the appropriate setter methods on the <literal
+ >HornetQConnectionFactory</literal> immediately after creating it.</para>
+ <para>If you're using the core API and instantiating the <literal
+ >ClientSessionFactory</literal> instance directly you can also specify the
+ parameters using the appropriate setter methods on the <literal
+ >ClientSessionFactory</literal> immediately after creating it.</para>
+ <para>If your client does manage to reconnect but the session is no longer available on the
+ server, for instance if the server has been restarted or it has timed out, then the
+ client won't be able to re-attach, and any <literal>ExceptionListener</literal> or
+ <literal>FailureListener</literal> instances registered on the connection or session
+ will be called.</para>
+ </section>
<section id="client-reconnection.exceptionlistener">
<title>ExceptionListeners and SessionFailureListeners</title>
-
-
- <para>Please note, that when a client reconnects or re-attaches, any registered JMS <literal
- >ExceptionListener</literal> or core API <literal>SessionFailureListener</literal> will
- be called.</para>
+ <para>Please note, that when a client reconnects or re-attaches, any registered JMS <literal
+ >ExceptionListener</literal> or core API <literal>SessionFailureListener</literal>
+ will be called.</para>
</section>
</chapter>
Deleted: trunk/docs/user-manual/en/command-buffering.xml
===================================================================
--- trunk/docs/user-manual/en/command-buffering.xml 2009-12-04 16:33:18 UTC (rev 8559)
+++ trunk/docs/user-manual/en/command-buffering.xml 2009-12-04 16:53:46 UTC (rev 8560)
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- ============================================================================= -->
-<!-- Copyright © 2009 Red Hat, Inc. and others. -->
-<!-- -->
-<!-- The text of and illustrations in this document are licensed by Red Hat under -->
-<!-- a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). -->
-<!-- -->
-<!-- An explanation of CC-BY-SA is available at -->
-<!-- -->
-<!-- http://creativecommons.org/licenses/by-sa/3.0/. -->
-<!-- -->
-<!-- In accordance with CC-BY-SA, if you distribute this document or an adaptation -->
-<!-- of it, you must provide the URL for the original version. -->
-<!-- -->
-<!-- Red Hat, as the licensor of this document, waives the right to enforce, -->
-<!-- and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent -->
-<!-- permitted by applicable law. -->
-<!-- ============================================================================= -->
-<chapter id="command-buffering">
- <title>Command Buffering</title>
- <para>As HornetQ clients send commands to their servers they store each sent command in an
- in-memory buffer. In the case that connection failure occurs and the client subsequently
- reconnects to the same server or fails over onto a backup server, as part of the
- reconnection protocol the server informs the client during reconnection with the id of the
- last command it successfully received from that client.</para>
- <para>If the client has sent more commands than were received before failover it can replay any
- sent commands from its buffer so that the client and server can reconcile their
- states.</para>
- <para>The size of this buffer is configured by the <literal>ProducerWindowSize</literal>
- parameter, when the server has received <literal>ProducerWindowSize</literal> bytes of
- commands and processed them it will send back a command confirmation to the client, and the
- client can then free up space in the buffer.</para>
- <para>If you are using JMS and you're using the JMS service on the server to load your JMS
- connection factory instances into JNDI then this parameter can be configured in <literal
- >hornetq-jms.xml</literal> using the element <literal>confirmation-window-size</literal> a.
- If you're using JMS but not using JNDI then you can set these values directly on the
- <literal>HornetQConnectionFactory</literal> instance using the appropriate setter
- method.</para>
- <para>If you're using core you can set these values directly on the <literal
- >ClientSessionFactory</literal> instance using the appropriate setter method.</para>
- <para>The send window is specified in bytes, and has a default value of <literal
- >1MiB</literal>.</para>
- <para>When the send buffer becomes full, any attempts to send more commands from the client will
- block until the client receives a confirmation from the server and clears out the buffer.
- Because of the blocking, the command buffer performs a type of <literal>flow
- control</literal>, preventing the client from overwhelming the server with
- commands.</para>
- <para>Setting this parameter to <literal>-1</literal> disables any flow control on
- sending.</para>
-</chapter>
Modified: trunk/docs/user-manual/en/configuration-index.xml
===================================================================
--- trunk/docs/user-manual/en/configuration-index.xml 2009-12-04 16:33:18 UTC (rev 8559)
+++ trunk/docs/user-manual/en/configuration-index.xml 2009-12-04 16:53:46 UTC (rev 8560)
@@ -985,10 +985,17 @@
<entry>-1</entry>
</row>
<row>
- <entry><link linkend="command-buffering"
+ <entry><link linkend="client-reconnection"
+ >connection-factory.producer-window-size</link></entry>
+ <entry>Integer</entry>
+ <entry>the window size in bytes for producers sending messages</entry>
+ <entry>1024 * 1024</entry>
+ </row>
+ <row>
+ <entry><link linkend="client-reconnection"
>connection-factory.confirmation-window-size</link></entry>
<entry>Integer</entry>
- <entry>the window size (in bytes) for sending messages</entry>
+ <entry>the window size (in bytes) for reattachment confirmations</entry>
<entry>1024 * 1024</entry>
</row>
<row>
Modified: trunk/docs/user-manual/en/master.xml
===================================================================
--- trunk/docs/user-manual/en/master.xml 2009-12-04 16:33:18 UTC (rev 8559)
+++ trunk/docs/user-manual/en/master.xml 2009-12-04 16:53:46 UTC (rev 8560)
@@ -34,8 +34,7 @@
<!ENTITY embedding-hornetq SYSTEM "embedding-hornetq.xml">
<!ENTITY examples SYSTEM "examples.xml">
<!ENTITY filter-expressions SYSTEM "filter-expressions.xml">
- <!ENTITY flow-control SYSTEM "flow-control.xml">
- <!ENTITY command-buffering SYSTEM "command-buffering.xml">
+ <!ENTITY flow-control SYSTEM "flow-control.xml">
<!ENTITY ha SYSTEM "ha.xml">
<!ENTITY transaction-config SYSTEM "transaction-config.xml">
<!ENTITY intercepting-operations SYSTEM "intercepting-operations.xml">
@@ -96,7 +95,6 @@
&connection-ttl;
&transaction-config;
&flow-control;
- &command-buffering;
&send-guarantees;
&undelivered-messages;
&message-expiry;
Modified: trunk/docs/user-manual/user-manual.xpr
===================================================================
--- trunk/docs/user-manual/user-manual.xpr 2009-12-04 16:33:18 UTC (rev 8559)
+++ trunk/docs/user-manual/user-manual.xpr 2009-12-04 16:53:46 UTC (rev 8560)
@@ -18,7 +18,6 @@
<file name="en/client-classpath.xml"/>
<file name="en/client-reconnection.xml"/>
<file name="en/clusters.xml"/>
- <file name="en/command-buffering.xml"/>
<file name="en/configuration-index.xml"/>
<file name="en/configuring-transports.xml"/>
<file name="en/connection-ttl.xml"/>
15 years, 1 month
JBoss hornetq SVN: r8559 - in trunk/tests/src/org/hornetq/tests/integration/cluster: failover and 1 other directories.
by do-not-reply@jboss.org
Author: ataylor
Date: 2009-12-04 11:33:18 -0500 (Fri, 04 Dec 2009)
New Revision: 8559
Modified:
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusterTestBase.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusterWithBackupTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusteredGroupingTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusteredRequestResponseTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/MessageRedistributionTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyFileStorageSymmetricClusterTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyFileStorageSymmetricClusterWithBackupTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyFileStorageSymmetricClusterWithDiscoveryTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyOneWayChainClusterTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyOneWayTwoNodeClusterTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettySymmetricClusterTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettySymmetricClusterWithBackupTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettySymmetricClusterWithDiscoveryTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/OneWayChainClusterTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/OnewayTwoNodeClusterTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/SymmetricClusterTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/SymmetricClusterWithDiscoveryTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/TwoWayTwoNodeClusterTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ClusterWithBackupFailoverTestBase.java
trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FileStorageDiscoveryClusterWithBackupFailoverTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FileStorageStaticClusterWithBackupFailoverTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/failover/GroupingFailoverTestBase.java
trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyFileStorageDiscoveryClusterWithBackupFailoverTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyFileStorageStaticClusterWithBackupFailoverTest.java
trunk/tests/src/org/hornetq/tests/integration/cluster/restart/ClusterRestartTest.java
Log:
remeoved all boolean isFileStorage() methods
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusterTestBase.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusterTestBase.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusterTestBase.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -1677,4 +1677,9 @@
}
}
}
+
+ protected boolean isFileStorage()
+ {
+ return true;
+ }
}
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusterWithBackupTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusterWithBackupTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusterWithBackupTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -58,11 +58,6 @@
{
return false;
}
-
- protected boolean isFileStorage()
- {
- return true;
- }
public void testBasicRoundRobin() throws Exception
{
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusteredGroupingTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusteredGroupingTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusteredGroupingTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -1016,11 +1016,6 @@
return true;
}
- public boolean isFileStorage()
- {
- return true;
- }
-
class ThreadSender implements Runnable
{
private int msgStart;
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusteredRequestResponseTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusteredRequestResponseTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/ClusteredRequestResponseTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -48,11 +48,6 @@
{
return false;
}
-
- protected boolean isFileStorage()
- {
- return true;
- }
public void testRequestResponse() throws Exception
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/MessageRedistributionTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/MessageRedistributionTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/MessageRedistributionTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -63,11 +63,6 @@
return false;
}
- protected boolean isFileStorage()
- {
- return true;
- }
-
public void testRedistributionWhenConsumerIsClosed() throws Exception
{
setupCluster(false);
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyFileStorageSymmetricClusterTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyFileStorageSymmetricClusterTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyFileStorageSymmetricClusterTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -26,10 +26,4 @@
{
return true;
}
-
- protected boolean isFileStorage()
- {
- return true;
- }
-
}
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyFileStorageSymmetricClusterWithBackupTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyFileStorageSymmetricClusterWithBackupTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyFileStorageSymmetricClusterWithBackupTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -36,10 +36,5 @@
{
return true;
}
-
- protected boolean isFileStorage()
- {
- return true;
- }
-
+
}
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyFileStorageSymmetricClusterWithDiscoveryTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyFileStorageSymmetricClusterWithDiscoveryTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyFileStorageSymmetricClusterWithDiscoveryTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -27,9 +27,5 @@
{
return true;
}
-
- protected boolean isFileStorage()
- {
- return true;
- }
+
}
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyOneWayChainClusterTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyOneWayChainClusterTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyOneWayChainClusterTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -33,9 +33,4 @@
{
return true;
}
-
- protected boolean isFileStorage()
- {
- return true;
- }
}
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyOneWayTwoNodeClusterTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyOneWayTwoNodeClusterTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettyOneWayTwoNodeClusterTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -33,12 +33,5 @@
{
return true;
}
-
- protected boolean isFileStorage()
- {
- return true;
- }
-
-
}
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettySymmetricClusterTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettySymmetricClusterTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettySymmetricClusterTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -29,9 +29,4 @@
{
return true;
}
-
- protected boolean isFileStorage()
- {
- return true;
- }
}
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettySymmetricClusterWithBackupTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettySymmetricClusterWithBackupTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettySymmetricClusterWithBackupTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -37,11 +37,6 @@
return true;
}
- protected boolean isFileStorage()
- {
- return true;
- }
-
public void _test() throws Exception
{
for (int i = 0; i < 50; i++)
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettySymmetricClusterWithDiscoveryTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettySymmetricClusterWithDiscoveryTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/NettySymmetricClusterWithDiscoveryTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -30,9 +30,4 @@
return true;
}
- protected boolean isFileStorage()
- {
- return true;
- }
-
}
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/OneWayChainClusterTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/OneWayChainClusterTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/OneWayChainClusterTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -58,11 +58,6 @@
return false;
}
- protected boolean isFileStorage()
- {
- return true;
- }
-
public void testBasicRoundRobin() throws Exception
{
setupClusterConnection("cluster0-1", 0, 1, "queues", false, 4, isNetty());
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/OnewayTwoNodeClusterTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/OnewayTwoNodeClusterTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/OnewayTwoNodeClusterTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -54,12 +54,8 @@
{
return false;
}
+
- protected boolean isFileStorage()
- {
- return true;
- }
-
/*
* make sure source can shutdown if target is never started
*/
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/SymmetricClusterTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/SymmetricClusterTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/SymmetricClusterTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -51,11 +51,6 @@
return false;
}
- protected boolean isFileStorage()
- {
- return true;
- }
-
public void testStopAllStartAll() throws Throwable
{
try
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/SymmetricClusterWithDiscoveryTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/SymmetricClusterWithDiscoveryTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/SymmetricClusterWithDiscoveryTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -37,11 +37,6 @@
return false;
}
- protected boolean isFileStorage()
- {
- return true;
- }
-
@Override
protected void setupCluster() throws Exception
{
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/TwoWayTwoNodeClusterTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/TwoWayTwoNodeClusterTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/distribution/TwoWayTwoNodeClusterTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -55,10 +55,6 @@
return false;
}
- protected boolean isFileStorage()
- {
- return true;
- }
public void testStartStop() throws Exception
{
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ClusterWithBackupFailoverTestBase.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ClusterWithBackupFailoverTestBase.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/ClusterWithBackupFailoverTestBase.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -75,11 +75,6 @@
return false;
}
- protected boolean isFileStorage()
- {
- return true;
- }
-
public void testFailAllNodes() throws Exception
{
setupCluster();
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FileStorageDiscoveryClusterWithBackupFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FileStorageDiscoveryClusterWithBackupFailoverTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FileStorageDiscoveryClusterWithBackupFailoverTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -32,8 +32,4 @@
*/
public class FileStorageDiscoveryClusterWithBackupFailoverTest extends DiscoveryClusterWithBackupFailoverTest
{
- protected boolean isFileStorage()
- {
- return true;
- }
}
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FileStorageStaticClusterWithBackupFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FileStorageStaticClusterWithBackupFailoverTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/FileStorageStaticClusterWithBackupFailoverTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -32,8 +32,4 @@
*/
public class FileStorageStaticClusterWithBackupFailoverTest extends StaticClusterWithBackupFailoverTest
{
- protected boolean isFileStorage()
- {
- return true;
- }
}
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/GroupingFailoverTestBase.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/GroupingFailoverTestBase.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/GroupingFailoverTestBase.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -234,10 +234,6 @@
abstract void setupMasterServer(int i, boolean fileStorage, boolean netty);
- public boolean isFileStorage()
- {
- return true;
- }
public boolean isNetty()
{
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyFileStorageDiscoveryClusterWithBackupFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyFileStorageDiscoveryClusterWithBackupFailoverTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyFileStorageDiscoveryClusterWithBackupFailoverTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -36,9 +36,4 @@
{
return true;
}
-
- protected boolean isFileStorage()
- {
- return true;
- }
}
\ No newline at end of file
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyFileStorageStaticClusterWithBackupFailoverTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyFileStorageStaticClusterWithBackupFailoverTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/failover/NettyFileStorageStaticClusterWithBackupFailoverTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -36,9 +36,4 @@
{
return true;
}
-
- protected boolean isFileStorage()
- {
- return true;
- }
}
Modified: trunk/tests/src/org/hornetq/tests/integration/cluster/restart/ClusterRestartTest.java
===================================================================
--- trunk/tests/src/org/hornetq/tests/integration/cluster/restart/ClusterRestartTest.java 2009-12-04 16:30:53 UTC (rev 8558)
+++ trunk/tests/src/org/hornetq/tests/integration/cluster/restart/ClusterRestartTest.java 2009-12-04 16:33:18 UTC (rev 8559)
@@ -199,8 +199,4 @@
return true;
}
- public boolean isFileStorage()
- {
- return true;
- }
}
15 years, 1 month
JBoss hornetq SVN: r8558 - trunk/docs/user-manual/en.
by do-not-reply@jboss.org
Author: timfox
Date: 2009-12-04 11:30:53 -0500 (Fri, 04 Dec 2009)
New Revision: 8558
Modified:
trunk/docs/user-manual/en/flow-control.xml
Log:
flow control docs
Modified: trunk/docs/user-manual/en/flow-control.xml
===================================================================
--- trunk/docs/user-manual/en/flow-control.xml 2009-12-04 16:10:51 UTC (rev 8557)
+++ trunk/docs/user-manual/en/flow-control.xml 2009-12-04 16:30:53 UTC (rev 8558)
@@ -184,9 +184,84 @@
server being overwhelmed.</para>
<section>
<title>Window based flow control</title>
- <para>HornetQ clients maintain a buffer of commands that have been sent to the server, thus
- provides a form of flow control. Please see <xref linkend="command-buffering"/> for more
- information on this.</para>
+ <para>In a similar way to consumer window based flow control, HornetQ producers, by
+ default, can only send messages to an address as long as they have sufficient credits to
+ do so. The amount of credits required to send a message is given by the size of the
+ message.</para>
+ <para>As producers run low on credits they request more from the server, when the server
+ sends them more credits they can send more messages.</para>
+ <para>The amount of credits a producer requests in one go is known as the <emphasis
+ role="italic">window size</emphasis>.</para>
+ <para>The window size therefore determines the amount of bytes that can be inflight at any
+ one time before more need to be requested - this prevents the remoting connection from
+ getting overloaded.</para>
+ <section>
+ <title>Using Core API</title>
+ <para>If the HornetQ core API is being window size can be set via the <literal
+ >ClientSessionFactory.setProducerWindowSize(int producerWindowSize)</literal>
+ method.</para>
+ </section>
+ <section>
+ <title>Using JMS</title>
+ <para>If JNDI is used to look up the connection factory, the producer window size can be
+ configured in <literal>hornetq-jms.xml</literal>:</para>
+ <programlisting>
+ <connection-factory name="ConnectionFactory">
+ <connectors>
+ <connector-ref connector-name="netty-connector"/>
+ </connectors>
+ <entries>
+ <entry name="ConnectionFactory"/>
+ </entries>
+ <producer-window-size>10</producer-window-size>
+ </connection-factory></programlisting>
+ <para>If the connection factory is directly instantiated, the producer window size can
+ be set via the <literal>HornetQConnectionFactory.setProducerWindowSize(int
+ producerWindowSize)</literal> method.</para>
+ </section>
+ <section>
+ <title>Blocking producer window based flow control</title>
+ <para>Normally the server will always give the same number of credits as have been
+ requested. However, it is also possible to set a maximum size on any address, and the
+ server will never send more credits than could cause the address's upper memory limit
+ to be exceeded.</para>
+ <para>For example, if I have a JMS queue called "myqueue", I could set the maximum
+ memory size to 10MiB, and the the server will control the number of credits sent to
+ any producers which are sending any messages to myqueue such that the total messages
+ in the queue never exceeds 10MiB.</para>
+ <para>When the address gets full, producers will block on the client side until more
+ space frees up on the address, i.e. until messages are consumed from the queue thus
+ freeing up space for more messages to be sent.</para>
+ <para>We call this blocking producer flow control, and it's an efficient way to prevent
+ the server running out of memory due to producers sending more messages than can be
+ handled at any time.</para>
+ <para>It is an alternative approach to paging, which does not block producers but
+ instead pages messages to storage.</para>
+ <para>To configure an address with a maximum size and tell the server that you want to
+ block producers for this address if it becomes full, you need to define an
+ AddressSettings (<xref linkend="queue-attributes.address-settings"/>) block for the
+ address and specify <literal>max-size-bytes</literal> and <literal
+ >address-full-policy</literal></para>
+ <para>The address block applies to all queues registered to that address. I.e. the total
+ memory for all queues bound to that address will not exceed <literal
+ >max-size-bytes</literal>. In the case of JMS topics this means the <emphasis
+ role="italic">total</emphasis> memory of all subscriptions in the topic won't
+ exceed max-size-bytes.</para>
+ <para>Here's an example:</para>
+ <programlisting>
+ <address-settings>
+ <address-setting match="jms.queue.exampleQueue">
+ <max-size-bytes>100000</max-size-bytes>
+ <address-full-policy>DROP</address-full-policy>
+ </address-setting>
+ </address-settings></programlisting>
+ <para>The above example would set the max size of the JMS queue "exampleQueue" to be
+ 100000 bytes and would block any producers sending to that address to prevent that
+ max size being exceeded.</para>
+ <para>Please note the default value for <literal>address-full-policy</literal> is to
+ <literal>PAGE</literal>. Please see the chapter on paging for more information on
+ paging.</para>
+ </section>
</section>
<section>
<title>Rate limited flow control</title>
15 years, 1 month
JBoss hornetq SVN: r8557 - in trunk/examples/jms/non-transaction-failover: src/org/hornetq/jms/example and 1 other directory.
by do-not-reply@jboss.org
Author: jmesnil
Date: 2009-12-04 11:10:51 -0500 (Fri, 04 Dec 2009)
New Revision: 8557
Modified:
trunk/examples/jms/non-transaction-failover/readme.html
trunk/examples/jms/non-transaction-failover/src/org/hornetq/jms/example/NonTransactionFailoverExample.java
Log:
updated non-transaction-failover example
Modified: trunk/examples/jms/non-transaction-failover/readme.html
===================================================================
--- trunk/examples/jms/non-transaction-failover/readme.html 2009-12-04 15:46:18 UTC (rev 8556)
+++ trunk/examples/jms/non-transaction-failover/readme.html 2009-12-04 16:10:51 UTC (rev 8557)
@@ -101,18 +101,9 @@
}
catch (JMSException e)
{
- System.out.println("Got exception while acknowledging message: " + e.getMessage());
- ...
+ System.err.println("Got exception while acknowledging message: " + e.getMessage());
}
</pre>
-
- <li>The client must cope with the failover and recreate the JMS session</li>
- <pre class="prettyprint">
- session.close();
- session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
- producer = session.createProducer(queue);
- consumer = session.createConsumer(queue);
- </pre>
<li>Consume again the second half of the messages againg. Note that they are not considered as redelivered</li>
<pre class="prettyprint">
@@ -124,26 +115,6 @@
message0.acknowledge();
</pre>
- <li>Send some more messages</li>
- <pre class="prettyprint">
- for (int i = numMessages; i < numMessages * 2; i++)
- {
- TextMessage message = session.createTextMessage("This is text message " + i);
- producer.send(message);
- System.out.println("Sent message: " + message.getText());
- }
- </pre>
-
- <li>Consume them</li>
- <pre class="prettyprint">
- for (int i = 0; i < numMessages; i++)
- {
- TextMessage message = (TextMessage)consumer.receive(5000);
- System.out.println("Got message: " + message.getText());
- message.acknowledge();
- }
- </pre>
-
<li>And finally, <strong>always</strong> remember to close your resources after use, in a <code>finally</code> block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects</li>
<pre class="prettyprint">
Modified: trunk/examples/jms/non-transaction-failover/src/org/hornetq/jms/example/NonTransactionFailoverExample.java
===================================================================
--- trunk/examples/jms/non-transaction-failover/src/org/hornetq/jms/example/NonTransactionFailoverExample.java 2009-12-04 15:46:18 UTC (rev 8556)
+++ trunk/examples/jms/non-transaction-failover/src/org/hornetq/jms/example/NonTransactionFailoverExample.java 2009-12-04 16:10:51 UTC (rev 8557)
@@ -104,15 +104,10 @@
}
catch (JMSException e)
{
- System.out.println("Got exception while acknowledging message: " + e.getMessage());
- // Step 12. Close the JMS session and recreate the JMS objects
- session.close();
- session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
- producer = session.createProducer(queue);
- consumer = session.createConsumer(queue);
+ System.err.println("Got exception while acknowledging message: " + e.getMessage());
}
- // Step 13. Consume again the 2nd half of the messages again. Note that they are not considered as redelivered.
+ // Step 12. Consume again the 2nd half of the messages again. Note that they are not considered as redelivered.
for (int i = numMessages / 2; i < numMessages; i++)
{
message0 = (TextMessage)consumer.receive(5000);
@@ -120,27 +115,11 @@
}
message0.acknowledge();
- // Step 14. Send some more messages
- for (int i = numMessages; i < numMessages * 2; i++)
- {
- TextMessage message = session.createTextMessage("This is text message " + i);
- producer.send(message);
- System.out.println("Sent message: " + message.getText());
- }
-
- // Step 15. Consume them
- for (int i = 0; i < numMessages; i++)
- {
- TextMessage message = (TextMessage)consumer.receive(5000);
- System.out.println("Got message: " + message.getText());
- message.acknowledge();
- }
-
return true;
}
finally
{
- // Step 16. Be sure to close our resources!
+ // Step 13. Be sure to close our resources!
if (connection != null)
{
15 years, 1 month