[interfacekit] BSession

First, let me summarise the state of affairs as I see it in CVS. Correct me if 
I'm wrong.

PROTOCOLS

status_t read_port_etc(port_id port, int32 *code, void *buffer, size_t 
bufferSize, uint32 flags,
bigtime_t timeout);

status_t write_port_etc(port_id port, int32 code, const void *buffer, size_t 
bufferSize, uint32
flags, bigtime_t timeout);

The "int32 code" parameter is NOT the BMessage's "what". Developers may use it 
as they wish, but
within the appserver and IK, it represents the message protocol, so we should 
write "int32
protocol". From /headers/private/app/ServerProtocol.h we have these protocols:

AS_SERVER_BMESSAGE - BMessenger/BMessage
AS_SERVER_AREALINK - BAreaLink
AS_SERVER_SESSION - BSession
AS_SERVER_PORTLINK - BPortMessage/BPortLink

The 'protocol' parameter is an attribute of the message that wil be retrieved 
when read_port_etc()
is called. It is not part of the data in the 'buffer' parameter. Additionally, 
the kernel exposes
the size attribute for the next message in the port via:

ssize_t port_buffer_size_etc(port_id id, uint32 flags, bigtime_t timeout)


AS_SERVER_PORTLINK

Currently, this is used for communication with the appserver by BAppliction.

BPortMessage implements a message protocol where the first 4-bytes of the data 
represents the
int32 BPortMessage::Code() used like 'what'. The next 4-bytes are reserved. 
These items are
automatically extracted from the data 'stream' (really a pointer to the local 
data buffer). The
remainder of the data items are extracted via:

status_t BPortMessage::Read(void *data, ssize_t size);
status_t BPortMessage::ReadString(char **string);
status_t BPortMessage::Read<class Type>(Type *data);

You have to know what data items to expect from the 'stream'. Unlike BMessage, 
the data isn't
tagged so you can't do random access e.g. FindInt32("width", &myint).

BPortMessage is mainly for reading. It is populated with ReadFromPort(). You 
can WriteToPort(),
but there a no functions for populating the buffer a data item at a time.

BPortLink is for writing only.

status_t BPortLink::Attach(const void *data, size_t size);
status_t BPortLink::AttachString(const char *string);
status_t Attach<class Type>(Type data)

After attaching the data items, and calling SetOpCode() a.k.a 'what' you can 
Flush() or
FlushWithReply() to write the message to the port. By protocol, 
FlushWithReply() appends an
additional data item to the data buffer representing the port_id of the port to 
reply to.

status_t PortLink::FlushToSession() will make sense later.


AS_SERVER_SESSION

Let's first remember read/write_port_etc() implements a message passing 
mechanism. When call
read_port_etc() you get a complete message or nothing. You won't get half a 
message, or more than
one. Message boundaries are preserved. This is unlike TCP/IP sockets where the 
kernel and drivers
are free to fragment or chunk the data stream as needed.

AS_SERVER_SESSION is a hybrid protocol. Instead of using logical message 
boundaries, it may
fragment on data item boundaries and/or pack more than one logical message into 
the port message.
It is used for communication between BWindow and the appserver where drawing 
instructions could be
numerous and latency could be an issue.

This is where I get suspicious.

Looking at how BSession is used in View.cpp and Window.cpp, it seems to allow 
more than one
logical message to be put into one port call. This makes sense if you have a 
lot of drawing
instructions, an array of lines, or simply wish to avoid the memory management 
and write_port()
overhead of multiple small messages. Sync() is called to then send the bundle 
of messages.

Protocol wise, the int32 'what' code is written, then the data items, then the 
next int32 'what'
code and then the data items. The receiver is assumed to know how many data 
items to expect, and
their type, based on the 'what' code.

Looking at the BSession implementation, write_port() is called for the 'what' 
and each data item.
This incurs a high overhead in sending/decoding in the number of port calls. 
The messages are
fragmented to single data items. I don't see the advantage of this since the 
server shouldn't
execute a command until it has checked all the parameters. The degree of 
parallelism this offers
is insignificant and it causes excessive context-switching.

Also BSession had all the return error codes removed. I'm unable to create 
robust software with
it.

void BSession::ReadData( void* data, int32 size );
void BSession::WriteData(const void* data, int32 size);
void BSession::Sync();

If we receive multiple logical messages in one port call, and the appserver 
does not recognize the
'what' of the first message, the remaining messages have to be dumped because 
we don't know where
the message boundaries are. What should be the policy here? Should the client 
be disconnected?

If the message is fragmented, and we don't recognise the 'what', then the whole 
session has to be
abandoned for the same reason. In the case of BWindow, the BWindow will have to 
be disconnected or
we need a seperate mechanism to re-synchronize.

If there is any deviation in the number or size of data items outside of what 
we expect, the whole
stream becomes out of sync without error detection. We could be reading bogus 
data without knowing
it as missing data is taken from the next message, and extra data becomes the 
head of the next
message.

In discussions relating to using server-side widgets for optimizations (e.g. in 
X11 debates),
people have often said that client-server communications for drawing widgets is 
a bottleneck that
doesn't exist.

In anycase, if we decided to have BSession as a streamlined protocol, I suggest 
it be only be used
for non-critical communications, such as drawing instructions. Structural or 
state change messages
should not use this protocol if we tolerate dropping messages in BSession.

Do we really need BSession? What problem is it meant to solve?

Cheers,
Paul.


        
                
__________________________________
Do you Yahoo!?
Yahoo! Small Business $15K Web Design Giveaway 
http://promotions.yahoo.com/design_giveaway/

Other related posts: