summaryrefslogtreecommitdiff
path: root/dotnet/Qpid.Codec/CumulativeProtocolDecoder.cs
diff options
context:
space:
mode:
Diffstat (limited to 'dotnet/Qpid.Codec/CumulativeProtocolDecoder.cs')
-rw-r--r--dotnet/Qpid.Codec/CumulativeProtocolDecoder.cs213
1 files changed, 113 insertions, 100 deletions
diff --git a/dotnet/Qpid.Codec/CumulativeProtocolDecoder.cs b/dotnet/Qpid.Codec/CumulativeProtocolDecoder.cs
index 72c56e0b17..3d454b284b 100644
--- a/dotnet/Qpid.Codec/CumulativeProtocolDecoder.cs
+++ b/dotnet/Qpid.Codec/CumulativeProtocolDecoder.cs
@@ -19,121 +19,134 @@
*
*/
using System;
+using log4net;
using Qpid.Buffer;
namespace Qpid.Codec
{
- public abstract class CumulativeProtocolDecoder : IProtocolDecoder
- {
- ByteBuffer _remaining;
+ public abstract class CumulativeProtocolDecoder : IProtocolDecoder
+ {
+ static ILog _logger = LogManager.GetLogger(typeof(CumulativeProtocolDecoder));
- /// <summary>
- /// Creates a new instance with the 4096 bytes initial capacity of
- /// cumulative buffer.
- /// </summary>
- protected CumulativeProtocolDecoder()
- {
- _remaining = ByteBuffer.Allocate(4096);
- _remaining.IsAutoExpand = true;
- }
+ ByteBuffer _remaining;
- /// <summary>
- /// Cumulates content of <tt>in</tt> into internal buffer and forwards
- /// decoding request to {@link #doDecode(IoSession, ByteBuffer, ProtocolDecoderOutput)}.
- /// <tt>doDecode()</tt> is invoked repeatedly until it returns <tt>false</tt>
- /// and the cumulative buffer is compacted after decoding ends.
- /// </summary>
- /// <exception cref="Exception">
- /// if your <tt>doDecode()</tt> returned <tt>true</tt> not consuming the cumulative buffer.
- /// </exception>
- public void Decode(ByteBuffer input, IProtocolDecoderOutput output)
- {
- if (_remaining.Position != 0) // If there were remaining undecoded bytes
- {
- DecodeRemainingAndInput(input, output);
- }
- else
- {
- DecodeInput(input, output);
- }
- }
+ /// <summary>
+ /// Creates a new instance with the 4096 bytes initial capacity of
+ /// cumulative buffer.
+ /// </summary>
+ protected CumulativeProtocolDecoder()
+ {
+ _remaining = AllocateBuffer();
+ }
- private void DecodeInput(ByteBuffer input, IProtocolDecoderOutput output)
- {
- // Just decode the input buffer and remember any remaining undecoded bytes.
- try
- {
- DecodeAll(input, output);
- }
- finally
+ /// <summary>
+ /// Cumulates content of <tt>in</tt> into internal buffer and forwards
+ /// decoding request to {@link #doDecode(IoSession, ByteBuffer, ProtocolDecoderOutput)}.
+ /// <tt>doDecode()</tt> is invoked repeatedly until it returns <tt>false</tt>
+ /// and the cumulative buffer is compacted after decoding ends.
+ /// </summary>
+ /// <exception cref="Exception">
+ /// if your <tt>doDecode()</tt> returned <tt>true</tt> not consuming the cumulative buffer.
+ /// </exception>
+ public void Decode(ByteBuffer input, IProtocolDecoderOutput output)
+ {
+ if ( _remaining.Position != 0 ) // If there were remaining undecoded bytes
+ {
+ DecodeRemainingAndInput(input, output);
+ } else
+ {
+ DecodeInput(input, output);
+ }
+ }
+
+ private void DecodeInput(ByteBuffer input, IProtocolDecoderOutput output)
+ {
+ _logger.Debug(string.Format("DecodeInput: input {0}", input.Remaining));
+ // Just decode the input buffer and remember any remaining undecoded bytes.
+ try
+ {
+ DecodeAll(input, output);
+ } finally
+ {
+ if ( input.HasRemaining )
{
- if (input.HasRemaining)
- {
- _remaining.Put(input);
- }
+ _remaining.Put(input);
}
- }
+ }
+ }
- private void DecodeRemainingAndInput(ByteBuffer input, IProtocolDecoderOutput output)
- {
- // Concatenate input buffer with left-over bytes.
- _remaining.Put(input);
- _remaining.Flip();
+ private void DecodeRemainingAndInput(ByteBuffer input, IProtocolDecoderOutput output)
+ {
+ _logger.Debug(string.Format("DecodeRemainingAndInput: input {0}, remaining {1}", input.Remaining, _remaining.Position));
+ // replace the _remainder buffer, so that we can leave the
+ // original one alone. Necessary because some consumer splice
+ // the buffer and only consume it until later, causing
+ // a race condition if we compact it too soon.
+ ByteBuffer newRemainding = AllocateBuffer();
+ ByteBuffer temp = _remaining;
+ _remaining = newRemainding;
+ temp.Put(input);
+ temp.Flip();
+ try
+ {
+ DecodeAll(temp, output);
+ } finally
+ {
+ if ( temp.Remaining > 0 )
+ _remaining.Put(temp);
+ }
+ }
- try
- {
- DecodeAll(_remaining, output);
- }
- finally
+ private void DecodeAll(ByteBuffer buf, IProtocolDecoderOutput output)
+ {
+ for ( ; ; )
+ {
+ int oldPos = buf.Position;
+ bool decoded = DoDecode(buf, output);
+ if ( decoded )
{
- _remaining.Compact();
- }
- }
+ if ( buf.Position == oldPos )
+ {
+ throw new Exception(
+ "doDecode() can't return true when buffer is not consumed.");
+ }
- private void DecodeAll(ByteBuffer buf, IProtocolDecoderOutput output)
- {
- for (;;)
+ if ( !buf.HasRemaining )
+ {
+ break;
+ }
+ } else
{
- int oldPos = buf.Position;
- bool decoded = DoDecode(buf, output);
- if (decoded)
- {
- if (buf.Position == oldPos)
- {
- throw new Exception(
- "doDecode() can't return true when buffer is not consumed.");
- }
-
- if (!buf.HasRemaining)
- {
- break;
- }
- }
- else
- {
- break;
- }
+ break;
}
- }
+ }
+ }
+
+ /// <summary>
+ /// Implement this method to consume the specified cumulative buffer and
+ /// decode its content into message(s).
+ /// </summary>
+ /// <param name="input">the cumulative buffer</param>
+ /// <param name="output">decoder output</param>
+ /// <returns>
+ /// <tt>true</tt> if and only if there's more to decode in the buffer
+ /// and you want to have <tt>doDecode</tt> method invoked again.
+ /// Return <tt>false</tt> if remaining data is not enough to decode,
+ /// then this method will be invoked again when more data is cumulated.
+ /// </returns>
+ /// <exception cref="Exception">If cannot decode</exception>
+ protected abstract bool DoDecode(ByteBuffer input, IProtocolDecoderOutput output);
- /// <summary>
- /// Implement this method to consume the specified cumulative buffer and
- /// decode its content into message(s).
- /// </summary>
- /// <param name="input">the cumulative buffer</param>
- /// <param name="output">decoder output</param>
- /// <returns>
- /// <tt>true</tt> if and only if there's more to decode in the buffer
- /// and you want to have <tt>doDecode</tt> method invoked again.
- /// Return <tt>false</tt> if remaining data is not enough to decode,
- /// then this method will be invoked again when more data is cumulated.
- /// </returns>
- /// <exception cref="Exception">If cannot decode</exception>
- protected abstract bool DoDecode(ByteBuffer input, IProtocolDecoderOutput output);
+ public void Dispose()
+ {
+ _remaining = null;
+ }
- public void Dispose()
- {
- _remaining = null;
- }
- }
+ private ByteBuffer AllocateBuffer()
+ {
+ ByteBuffer buffer = ByteBuffer.Allocate(4096);
+ buffer.IsAutoExpand = true;
+ return buffer;
+ }
+ }
}