Re: TriFork CORBA donation
How are things going? Do you think that it's possible to get the code in our repo and you work from there? Regards, Alan Kresten Krab Thorup wrote, On 9/16/2005 9:04 AM: 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,
Re: TriFork CORBA donation
Kresten Krab Thorup wrote: Hi there, ... Hi Kresten, I'm not prepared to comment on the details, but have a general question. - nio/select is used to avoid having an active thread listening for incoming messages It sounds like Java 5. Will it require this Java version? Geronimo is 1.4-based. Kresten Krab Thorup Jacek
Re: TriFork CORBA donation
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);
TriFork CORBA donation
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