You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mina.apache.org by Yigal Rachman <yi...@uvic.ca> on 2007/08/09 18:01:53 UTC

How to deal with dynamically changing line terminators?

Hi, Folks:

I have a MINA client that acts as a driver for a scientific instrument.  
The communication is via a serial link using ASCII.  The messages from 
the instrument are usually terminated with a line feed, but are 
sometimes terminated with a ">" instead (when it is prompting for commands).

Could you please suggest a design pattern that would do this elegantly 
in MINA?  I expect it will use the TextLineCodec and possibly some other 
filters, but I am fuzzy on the details.

Best regards,
Yigal Rachman

DMAS Data Acquisition Developer
NEPTUNE Canada
University of Victoria,
Victoria, BC, Canada
www.neptunecanada.ca

Re: How to deal with dynamically changing line terminators?

Posted by Adam Fisk <a...@lastbamboo.org>.
There's likely an easier way, though, to, like taking the TextLineCodec code
and just tweaking it to also look for ">".  My last suggestion is an elegant
way to do it, but it would require much more work.

-Adam


On 8/12/07, Adam Fisk <a...@lastbamboo.org> wrote:
>
> I'd give the state machine in AsyncWeb a look, as well as some of the
> helper classes.  The state machine approach takes awhile to wrap your head
> around if you're not used to it, but it works well.  The
> "ConsumeToDynamicTerminatorDecodingState" helper class will do exactly what
> you want.  You would need to write a fair bit of custom state machine code
> for your protocol going this route, but I think it's worth it.
>
> http://docs.safehaus.org/display/ASYNCWEB/Home
>
> -Adam
>
>
> On 8/9/07, Yigal Rachman <yi...@uvic.ca> wrote:
> >
> > Hi, Folks:
> >
> > I have a MINA client that acts as a driver for a scientific instrument.
> > The communication is via a serial link using ASCII.  The messages from
> > the instrument are usually terminated with a line feed, but are
> > sometimes terminated with a ">" instead (when it is prompting for
> > commands).
> >
> > Could you please suggest a design pattern that would do this elegantly
> > in MINA?  I expect it will use the TextLineCodec and possibly some other
> > filters, but I am fuzzy on the details.
> >
> > Best regards,
> > Yigal Rachman
> >
> > DMAS Data Acquisition Developer
> > NEPTUNE Canada
> > University of Victoria,
> > Victoria, BC, Canada
> > www.neptunecanada.ca
> >
>
>

Re: How to deal with dynamically changing line terminators?

Posted by Adam Fisk <a...@lastbamboo.org>.
Ahh -- I might just have an older version checked out, although I'm not
seeing anything newer in the repository.

Below is the whole class regardless.  The key is the isTerminator abstract
method.  A more efficient way might be to pass however many terminators you
want in a varargs constructor to avoid the abstract method call -- I think I
did that at one point.

Good luck.

-Adam


public abstract class ConsumeToDynamicTerminatorDecodingState implements
DecodingState {

  private ByteBuffer buffer;

  /**
   * Creates a new instance.
   */
  public ConsumeToDynamicTerminatorDecodingState() {
  }

  public DecodingState decode(ByteBuffer in, ProtocolDecoderOutput out)
throws Exception {
    int beginPos = in.position();
    int terminatorPos = -1;
    int limit = in.limit();

    for (int i = beginPos; i < limit; i ++) {
      byte b = in.get(i);
      if (isTerminator(b)) {
        terminatorPos = i;
        break;
      }
    }

    if (terminatorPos >= 0) {
      ByteBuffer product;

      if (beginPos < terminatorPos) {
        in.limit(terminatorPos);

        if (buffer == null) {
          product = in.slice();
        } else {
          buffer.put(in);
          product = buffer.flip();
          buffer = null;
        }

        in.limit(limit);
      } else {
        // When input contained only terminator rather than actual data...
        if (buffer == null) {
          product = ByteBuffer.allocate(1);
          product.limit(0);
        } else {
          product = buffer.flip();
          buffer = null;
        }
      }
      in.position(terminatorPos + 1);
      return finishDecode(product, out);
    } else {
      if (buffer == null) {
        buffer = ByteBuffer.allocate(in.remaining());
        buffer.setAutoExpand(true);
      }
      buffer.put(in);
      return this;
    }
  }

  protected abstract boolean isTerminator(byte b);

  protected abstract DecodingState finishDecode(ByteBuffer product,
ProtocolDecoderOutput out) throws Exception;
}

On 8/13/07, Yigal Rachman <yi...@uvic.ca> wrote:
>
>  Hi, Adam:
>
> Thank you for pointing me to AsyncWeb - really interesting stuff!  I found
> ConsumeToCRLFDecoder and ConsumeToCharacterDecoder, but no
> ConsumeToDynamicTerminatorDecodingState.  Any idea where I might find this?
>
> BTW, I have already coded some of my driver using state machines, and am
> 100% sold on this way of doing things.  It is amazingly efficient for
> managing i/o transactions of arbitrary duration because it does not keep
> threads waiting.
>
> - Yigal
>
>
> Adam Fisk wrote:
>
> I'd give the state machine in AsyncWeb a look, as well as some of the helper
> classes.  The state machine approach takes awhile to wrap your head around
> if you're not used to it, but it works well.  The
> "ConsumeToDynamicTerminatorDecodingState" helper class will do exactly what
> you want.  You would need to write a fair bit of custom state machine code
> for your protocol going this route, but I think it's worth it.
>
> http://docs.safehaus.org/display/ASYNCWEB/Home
>
> -Adam
>
>
> On 8/9/07, Yigal Rachman <yi...@uvic.ca> <yi...@uvic.ca> wrote:
>
>  Hi, Folks:
>
> I have a MINA client that acts as a driver for a scientific instrument.
> The communication is via a serial link using ASCII.  The messages from
> the instrument are usually terminated with a line feed, but are
> sometimes terminated with a ">" instead (when it is prompting for
> commands).
>
> Could you please suggest a design pattern that would do this elegantly
> in MINA?  I expect it will use the TextLineCodec and possibly some other
> filters, but I am fuzzy on the details.
>
> Best regards,
> Yigal Rachman
>
> DMAS Data Acquisition Developer
> NEPTUNE Canada
> University of Victoria,
> Victoria, BC, Canada
> www.neptunecanada.ca
>
>
>

Re: How to deal with dynamically changing line terminators?

Posted by Adam Fisk <a...@lastbamboo.org>.
I'd give the state machine in AsyncWeb a look, as well as some of the helper
classes.  The state machine approach takes awhile to wrap your head around
if you're not used to it, but it works well.  The
"ConsumeToDynamicTerminatorDecodingState" helper class will do exactly what
you want.  You would need to write a fair bit of custom state machine code
for your protocol going this route, but I think it's worth it.

http://docs.safehaus.org/display/ASYNCWEB/Home

-Adam


On 8/9/07, Yigal Rachman <yi...@uvic.ca> wrote:
>
> Hi, Folks:
>
> I have a MINA client that acts as a driver for a scientific instrument.
> The communication is via a serial link using ASCII.  The messages from
> the instrument are usually terminated with a line feed, but are
> sometimes terminated with a ">" instead (when it is prompting for
> commands).
>
> Could you please suggest a design pattern that would do this elegantly
> in MINA?  I expect it will use the TextLineCodec and possibly some other
> filters, but I am fuzzy on the details.
>
> Best regards,
> Yigal Rachman
>
> DMAS Data Acquisition Developer
> NEPTUNE Canada
> University of Victoria,
> Victoria, BC, Canada
> www.neptunecanada.ca
>