Handling the _IO_READ message
struct _io_read {
uint16_t type;
uint16_t combine_len;
uint32_t nbytes;
uint32_t xtype;
uint32_t zero;
};
struct _io_read64 {
uint16_t type;
uint16_t combine_len;
uint32_t nbytes;
uint32_t xtype;
uint32_t nbytes_hi;
};
typedef union {
struct _io_read i;
struct _io_read i64;
/* unsigned char data[nbytes]; */
/* nbytes is returned with MsgReply */
} io_read_t;
As with all resource manager messages, we've defined a union that contains the input (coming into the resource manager) structure and a reply or output (going back to the client) structure. The io_read handler is prototyped with an argument of io_read_t *msg—that's the pointer to the union containing the message.
Since this is a read(), the type member has the value _IO_READ or _IO_READ64. The client library uses the _IO_READ64 form only when the length is greater than 4 GB. The items of interest in the input structure are:
- combine_len
- This field has meaning for a combine message—see the Combine Messages chapter.
- nbytes
- How many bytes the client is expecting. For an _IO_READ64 message, the high 32 bits of the length are in nbytes_hi.
- xtype
- A per-message override, if your resource manager supports it.
Even if your resource manager doesn't support it, you should still examine this member.
More on the xtype later (see the
Handling the xtype member
section). - nbytes_hi
- (_IO_READ64 only) The high 32 bits of the length.
num_bytes = _IO_READ_GET_NBYTES(msg);
We'll create an io_read handler
that actually returns some data (the fixed string
"Hello, world\n"
).
We'll use the OCB to keep track of our position within the buffer that we're returning to the client.
read (fd, buf, 4096);
In this case, it's a simple matter to return our entire
"Hello, world\n"
string in the output buffer
and tell the client that we're returning 13 bytes, i.e., the size of the string.
while (read (fd, &character, 1) != EOF) {
printf ("Got a character \"%c\"\n", character);
}
Granted, this isn't a terribly efficient way for the client to perform reads!
In this case, we would get msg->i.nbytes
set to 1
(the size of the buffer that the client wants to get).
We can't simply return the entire string all at once to the client—we have to hand it out
one character at a time.
This is where the OCB's offset member comes into play.