> From: Niklas Therning <[EMAIL PROTECTED]>
> Subject: Re: Client operation of mina statemachine difficulty
> To: [email protected]
> Date: Tuesday, October 14, 2008, 6:54 PM
> [EMAIL PROTECTED] wrote:
> > Hi,
> >
> > I'm trying to use the mina statemachine in a
> client and I'm having trouble changing states
> programatically. After my client connects to a server there
> is an initial message exchange, and then my state machine
> goes into a ready state. Now if my client wants to send a
> "request detailed info" message to the server, I
> would like to put the state machine into
> "waitingForDetails" state, so that my
> statemachine/iohandler will be prepared to process the
> messages sent back.
> >
>
> Could you try to explain your protocol a bit more?
> Can't you just add a
> handler method for the "detailed info"
> message when in the
> "ready" state? Something like:
>
> @IoHandlerTransition(on = MESSAGE_RECEIVED, in =
> ReadyState)
> void handle(IoSession session,
> DetailedInfoMessage m) {
> ...
> }
Yes, for this particular message that would work because the
detailedInfoMessage is unique. It may very well be that my
problem is just a blind spot developed from the current
(non-mina) implementation that for each "command type" it
enters a corresponding state and then sends requests and listens for the
responses and moves through the successive states until the command is complete.
Here is a description of our protocol flow for transfering a file, where
my mina code would be "The tool" and the server I am talking to is "The device":
1. The tool initiates the file send by issuing a Memory Query
message requesting the devices available memory for the specified
FileType.
2. The device responds with a Memory Response message with the
amount of storage memory available for the specified FileType.
3. The tool confirms that the device contains enough storage memory to allow
for storage of the file in question.
4. The tool sends a File Transfer Receive Request message to initiate the
transfer of the file. This message includes the approximate file size
to be sent.
5. The device sends a File Transfer Receive Response message, which contains
the maximum data sector size accepted, to continue the transfer. Or the
device sends a Nak to indicate the operation can not be completed.
6a. Upon receipt of a File Transfer Nak by the tool, the transfer is aborted.
6b. Upon receipt of the File Transfer Receive Response, the tool sends the
first sector of data to the device via a File Transfer Data message.
The size of the sector may be up to the size specified by the Receive
Response message.
7. If the device receives and stores the data without error, it sends a File
Transfer Ack to the tool-otherwise it sends a File Transfer Nak with the
appropriate return code.
8a. Upon receipt of a File Transfer Nak, the tool aborts the transfer and
provides a message to the user (based upon the Nak FailureCode).
8b. Upon receipt of the File Transfer Ack, if any data remains to be sent
the tool sends the next sector of data. If there is no more data to send,
the tool sends a File Transfer End of Transfer. Steps 7 & 8 repeat until
all data has been transferred.
9. Finally, the receiving device responds to the EOT with an EOTR.
So I could have a handler such as:
@IoHandlerTransition(on = MESSAGE_RECEIVED, in = ReadyState)
void handle(IoSession session, MemoryResponse m) {
...
}
I can send a MemoryQueryMessage under two conditions, one as part of a file
transfer as above, but I can also send it as a stand alone command as a
result of user request. If I'm not able to preset the state according to the
command I'm implementing, I'm not sure how this handler will know whether
it should proceed with step 3 processing or it is done and should return data
because it was just a simple query.
>
> If you want to do a transition to a new state which handles
> the same
> message you can use StateControl.breakAndGotoNow() to
> immediately jump
> to another state.
>
> > I tried to use the StateControl.breakAndGotoNext(),
> but this doesn't work because the entity in the client
> that is initiating the send is not on the statemachine
> thread.
> >
> >
> Correct, you can only call StateControl.break* from within
> a handler
> method called by the statemachine proxy. If that's not
> possible you need
> to trigger an event on the state machine by calling a
> method on your
> IoHandler, e.g. messageReceived() and pass a special
> message object.
I would be interested in learning more about this. Otherwise I
think I will have to move most of my state processing out of the
IoHandler back to my service that utilizes the mina layer.
>
> > I tried keying off the sent message in the
> statemachine using
> > @IoHandlerTransition(on = MESSAGE_SENT,...l) to put it
> into the correct state but this doesn't work all the
> time. What I was seeing, is that sometimes my
> statemachine/iohandler was getting (reading) and processing
> a response to my request before my statemachine would
> process the @IoHandlerTransition(on = MESSAGE_SENT,...l), so
> I would be in the wrong state. Is this a bug?
> >
>
> No, I don't think it is. This is the way MINA works.
> It's not guaranteed
> that if you call session.write() you will get the
> MESSAGE_SENT event
> back before any other event is received.
>
> HTH
>
> /Niklas
-Rick