geronimo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Kresten Krab Thorup <k...@trifork.com>
Subject Re: TriFork CORBA donation
Date Fri, 16 Sep 2005 16:04:10 GMT
Hi there, ...

It has been up to a slow start, but I have finally gotten something  
rolling now.

As I have mentioned earlier, I wanted to redo the I/O subsystem, and  
this is going quite well.  The first milestone I am targeting is to  
be able to do client side stream-based invocations; i.e. be able to  
do invocations using a generated stub.  This is a sufficiently small  
thing that it is doable relatively quick (sigh), and also gets around  
to do most of the hairy parts of I/O.

This part I am writing from scratch, since the new I/O transcends  
most of this code.  This part is quite close to completion, and if  
someone wants to see the code I'd be happy to share it.  Here, I have  
some notes on the I/O system; ...

The I/O system is designed with the following properties:

- it eliminates copying (double buffering)
- i/o can be off-loaded to a separate selector thread
- nio/select is used to avoid having an active thread listening for  
incoming messages
- transport buffers are allocated only once, and have fixed size.
- facilitate multiplexing requests and bidirectional invocations.

In this terminology, a transport (which may be a socket or an in- 
memory pipe, for instance) has the following API:

interface Transport {

    InputChannel getInputChannel();
    OutputChannel getOutputChannel();
    void setInputHandler(InputHandler handler);
    void close();
    void start();

    void signalCondition(Object conditionKey, Object user_data);
    Object waitForCondition(Object conditionKey);
}

Only one thread can have the input channel at one time, and only one  
thread can have the output channel.  Calls to getInputChannel(), and  
getOutputChannel() will block until the channel is available.  If  
someone else has "taken" the channel, then the requestor will block  
until the other party relinquishes it.  This semantics is used to  
handle multiplexing multiple client threads using the same transport  
to do invocation, and similarily on the server side to  handle  
multiple threads sending responses.

interface Channel {
    void close();
    void relinquish();
}

Closing a channel semantically puts an end-of-stream marker into the  
channel's data.  For an OutputChannel, once the EOS reaches the  
underlying transport layer (i.e. the data ahead of it has been  
written), it is effectuated as a half-close.  For an InputChannel,  
the half-close is effectuated right away, and the client of the input  
stream will read and end-of-file when there is no more buffered data  
available.

When input becomes available in the underlying transport, and there  
is no current thread that owns the input channel, then control is  
passed to the input handler in a new thread taken from some worker pool.

The transport also has a built-in signaling mechanism, that allows  
the InputHandler to parse a message header (including e.g. a  
request_id) and then pass control to someone waiting for a given  
reply.  Such waiters can also participate in the processing of  
available input.

An output channel allows you to put data into the transport, and  
provides a mechanism to set markers.  Markers are used to handle  
fragmentation and other things where a size needs to be written into  
some place in the stream.

interface OutputChannel extends Channel {
     putByte(byte value);
     put(byte[] data, int off, int len);
     // ... other put methods ...

    void flush();

    OutputChannelMark setMark(OutputChannelMarkHandler handler);
}

Now, if the output channel's buffer runs full, then the mark handler  
is called, so that the

interface OutputChannelMarkHandler {
    void willFlush(OutputChannelMark mark);
}

OutputChannelMark provides a ByteBuffer-like view of the stream,  
where index 0 is the position of the marker.  You cannot put data  
beyond the mark's limit, which is equal to the amount of bytes  
written to the channel since the mark.

interface OutputChannelMark {
     void putByte(int idx, byte value);
     void putInt(int idx, int value);
     int limit();
     void release();
     OutputChannel getOutputChannel();
}

Calling release() on an OutputChannelMark will release underlying  
buffer space up to this mark (unless of cause there is a non-released  
marker that was set earlier in the stream).

The OutputChannelMark can also give you the channel that i came from,  
and so inside the handler you can do stuff like this to handle GIOP  
fragmentation dynamically based on when the underlying buffer runs full.

    class FragmentHandler implements OutputChannelMarkHandler {

        void willFlush( OutputChannelMark mark) {
             int message_size = mark.limit();
             if (!logical_stream_has_ended) {
                 mark.putByte(7, 2); // write "hasMoreFragments" bit
             }
             mark.putInt (8, message_size);  // write message size  
into GIOP header

             mark.release();

            if (!logical_stream_has_ended) {
                 mark.getOutputChannel().setMark(this);
                 write_fragment_header();
             }
        }

    }

I use the markers to implement GIOP fragments, and also to do  
chunking for values.  The mechanism cannot really be used for  
encapsulations because they can span GIOP messages.

So, ... on top of this abstraction layer I have implemented a fair  
chunk of the GIOP/CDR encoding stuff up to the point where a client  
can perform a request, but it doesn't work yet...

My thinking is that once this has reached a point where I can  
actually do a hello world invocation on a foreign ORB, then it would  
be a good point to bring in some more people.

Once we're past this, I have some larger chunks of the original  
Trifork ORB that we can bring to play.  You're welcome to have a look  
at the code though, and chip in with your comments.


Kresten Krab Thorup
krab@trifork.com

"We do not inherit the Earth from our parents, we borrow it from our  
children." Saint Exupery



On Sep 15, 2005, at 10:46 PM, Alan D. Cabrera wrote:

> How are things going on this?
> I hope that what will be donated will not be "gold plated" so that  
> the community can participate in its integration into Geronimo.  I  
> know that a few people, including people from OpenORB, are  
> interested in helping out.
>
>
> Regards,
> Alan
>
>
>
>


Mime
View raw message