Hi Olov, emmanuel
I forward your questions to the Jonathan list since Bruno, who wrote Jonathan, or others may have additional comments. To suscribe, see
        http://www.objectweb.org/resources/mailinglists.htm

hope this provides some hints.

Question 1 : The proposed sequence will not work.

    chunks = Marshaller.getStatus()
    for each chunk in chunks {
            Marshaller.reset()
            chunk.next = null
            Marshaller.write(chunk)
            SendDown(Marshaller)
    }

Indeed, a Marshaller instance cannot be reused after it has be transmitted to a lower layer protocol (or a MessageAdaptor with your terminology). It becomes this lower protocol responsability to make : write, reset, close... on it.
What you can do is to create a new marshaller at each step of the loop. Something like

    chunks = Marshaller.getStatus()
    Marshaller.reset(); // this Marshaller will not be used any more
    for each chunk in chunks {
            chunk.next = null
           newMarshaller = marshallerFactory.newMarshaller()
           newMarshaller.write(chunk)
            SendDown(newMarshaller)
    }

Where marshallerFactory is obtained, for example, as follow
    kernel = Kernel.init(null, null)
    marshallerFactory = StdMarshallerFactory.init(kernel)

Note that adding a simple header during this loop can be done as follow

    chunks = Marshaller.getStatus()
    Marshaller.reset(); // this Marshaller will not be used any more
    for each chunk in chunks {
            chunk.next = null
            newMarshaller = marshallerFactory.newMarshaller()
           newMarshaller.writeInt(...)  // for example if the header is an "int"
            newMarshaller.write(chunk)
            SendDown(newMarshaller)
    }
 
 

Question 2 : right,  a Marshaller has its own pointers that may possibly interfer with manual changes. Again, a possible approach is to
1 - first, obtain the chain of chunk (by Marshaller.getStatus()) delivered by the upper layer protocol
2 - do the protocol job (e.g. fragmentation of a chain of chunk, agregation of several chains of chunk, chunk duplication, addition of of header chunks... or anything you want).
3 - get new marshaller each time you need to send down updated data to the lower layer protocol.

The only constraint, during step 2, is to not exceed the network mtu. A possible solution is, for example, to consider that each protocol propagates (e.g. at binding time) its own "mtu"  to its upper layer protocol.
    Where a given protocol mtu = its lower layer mtu - its header size.

Finally, the approach you propose : <<chunks allocated at the top level protocol with exactly the size of the lower layer mtu>> is certainly the most efficient, when relevant, but maybe not adapted for all functionnalities (think of a protocol trying to aggregate small messages for example).
Unfortunately, I don't know the best use of Jonathan APIs to do that.
Maybe Bruno will have some sugestions ?

Nicolas

ps : if you are realy interested in chunk, Jonathan has a nice JChunkFactory (see package org.objectweb.jonathan.libs.ressources) that provides you pooling (chunk size and pool size are manageable) and optimisation for data duplication (avoid useless copy of memory).
 
 

 
Frederic Dang Tran wrote:
-----Original Message-----
From: Olov Stahl [mailto:[EMAIL PROTECTED]]
Sent: jeudi 3 mai 2001 12:35
To: DANGTRAN Frederic FTRD/DTL
Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED]
Subject: Jonathan (second try)

Sorry about the previous message, it got sent to early :-)

I have some questions regarding the Marshaller semantics in Jonathan.
Internally within the network channel objects that we are designing, we
will have stacks of something we (currently) call MessageAdaptors. This
is
similar to the Jonathan "stack" objects which implements the
Session_High
and Session_Low interfaces:

   NetworkChannel
--------------------
|                  |
|  MessageAdaptor  |
|  --------------  |
|  |            |  |
|  |            |  |
|  --------------  |
|       | ^        |
|       v |        |
|  MessageAdaptor  |
|  --------------  |
|  |            |  |
|  |            |  |
|  --------------  |
|       | ^        |
|       v |        |
|                  |
--------------------

The MessageAdaptor interface specifies a sendUp and sendDown method,
which takes a Marshaller argument

public interface MessageAdaptor {
   ...

   void sendUp(UnMarshaller m);

   void sendDown(Marshaller m);

   ...
}

Each MessageAdaptor object may potentially add a header to the message
before sending it on downward. The header of a given adaptor must be
written before the header of the "above" adaptor in order to be read in
the correct order on the receiving side. In Jonathan I think the prepare
method of the Session_High interface is used for this. Our problem is
that the Marshaller may contain a list of chunks, not just one, and the
total data contained within all those chunks may exceed the network mtu.
This means that I basically want to treat each chunk as one message (to
be sent on to the network), and I will need to add a header to each
chunk (by the way, this is exactly how its done in Dive).

My idea is to make sure that chunks allocated by the Marshaller are
exactly the size of the mtu (which depends on the channel), and that
each chunk will include a header area (the total header size of all the
adaptors in the channel) as well as an "data" area

Chunk

---------------------
|     |             |   size == mtu of channel
|     |             |
---------------------
  hdr       data

hdr is the combined hdr info of all adaptors in the channel
data is the data added by "anyone" (clients) outside the channel

We believe that the data section will be written before the header
section (since the clients fill the marshaller with data before sending
it to the channel). We can't make use of a prepare method since before
the clients have written their data we don't know how many chunks will
be allocated (and thus how many headers).

So, when the Marshaller is sent down to the channel we assume it will
look something like this:

Marshaller -> chunk -> chunk -> chunk ->

            -------    -------  -------
            | |\\\|    | |\\\|  | |\\\|
            -------    -------  -------

Each chunk will have a "filled" data section and an empty header
section. When sending this marshaller down the adaptor chain, each
adaptor will need to write its header data into the correct position in
the header section of EVERY chunk, not just one.

My idea of how to do this is the following:

* At the highest level in the channel, get a handle to all the chunks
and then reset the marshaller =>

myHandle -> -------     -------    -------
            | |\\\| ->  | |\\\| -> | |\\\| ->
            -------     -------    -------

Marshaller ->

This is done by using the Marshaller.getStatus() and Marshaller.reset()
methods.

* For each chunk in the list, remove the next reference, insert the
chunk into the marshaller (the same one), and send the marshaller down
the adaptor chain

chunks = Marshaller.getStatus()
for each chunk in chunks {
        Marshaller.reset()
        chunk.next = null
        Marshaller.write(chunk)
        SendDown(Marshaller)
}

The idea being that the adaptors will receive a series of Marshallers
with only one chunk of the correct mtu size, instead of one Marshaller
containing a list of chunks. For each such Marshaller, the adaptors
write their header data into the correct position of the header section
(will include fiddeling with the chunk offset pointers) and send the
Marshaller downwards. The reason for doing the resest-write is that I
want adaptors to be able to use the Marshaller to code their header data
into the chunk. If they were responsible for doing their own coding, we
could just send chunks (not marshallers) down the adaptor chain, and
each adaptor would write its header data by indexing the chunk byte
array directly.

Questions:

1. Is it possible to use the reset() and write() methods of the
Marshaller interface in the way I have described above, i.e., to first
empty the Marshaller and then to reinsert a chunk that the Marshaller
will use to store data? When I look at the implementation of the
StdMarshaller inside StdMarshallerFactory.java, it seems that calling
write(chunk) after an reset() will cause an error (write assumes there
is a "current chunk, which there won't be if I have called reset)

2. If I get a handle to a chunk used by a Marshaller and then change the
top and offset pointers of the chunk, will the Marshaller honour these
changes? StdMarshaller seems to use their own index pointers, which
won't be affected by a change to the chunk's pointers. What I want to do
is to change the chunk index pointers and then call for instance
Marshaller.writeInt() to write an integer into a specific position of
the chunk.

- Olov

Reply via email to