[Dionysix Design Notes]

Dionysix Reference

Dp server

Buffered Request Streams

D R A F T

Description

Introduction

The set of functions and strucutres that make up the Buffered Request Streams library provide a means to perform blocking I/O using a single-threaded, non-blocking dp server.

Server objects which utilize Buffered Request Streams do not guarantee that reads and writes will complete immediately. Reads and writes on these objects will complete eventually; notification is normally sent to the client by means of an IoWait invocation.

Requirements

Dp Servers that implement blocking I/O need a way to accept and buffer Tread and Twrite commands. The server itself must promptly return to fufill other requests. In other words, the server cannot wait while trying to satisfy a Tread on, say, an empty pipe. Instead, the server needs to buffer the Tread until it can be satisfied.

Furthermore, blocking I/O servers need a way to remove buffered requests according to their tag. Therefore, while an object in the server maintains a continuous "stream" of data, it must also keep track of which data is associated with which request.

Finally, the server must work with a fixed buffer area -- that is, no memory can be dynamically allocated during server operation.

Implementation

The primary structure in this library is the buf_stream, which implements a doubly-linked list of buffers, each containing Tread or Twrite requests, depending on the type of buf_stream. Requests can be
  1. appended to a buf_stream,
  2. fufilled by a data xfer between a two buf_streams, or
  3. removed from a buf_stream at any time prior to being fufilled.
Buf_streams guarantee that requests will be fufilled in the order in which they were sent. Also guaranteed is an R-response (Rread, Rwrite, Rerror) for each Tread or Twrite removed from a buf_stream, unless it is removed by a Tflush, in which case no response is sent.

Internally, each buf_stream takes buffers from the doubly-linked circular global buffer list as needed, and relinquishes them as requests are completed. Hence, the number of request buffers is not dependent on the number of buffered request streams. Instead, the number of request buffers is #defined by REQ_BUFS in srvr-params.h.

The typical server configuration (Fig. 1) has two buf_streams, one containing Twrite requests and the other containing Tread requests.


Fig 1: Two streams in a pipe server or an IP server.

Whenever a Tread or Twrite request is sent to the server, it should be added to the buf_stream using AppendReadRequest or AppendWriteRequest. After any Append- function call, the server should attempt a to satisfy some of the requests pending in its buf_streams by performing an Xfer command. Tabort requests should utitlize the RemoveRequest function.


Functions

InitGlobalBufs ()

Initialize a the global buffer list. Must be called before any of the buffered request streams functions are used.

InitBufStream (buf_stream *st)

Initialize a buf_stream.

AppendWriteRequest (buf_stream *st, Word session, HalfWord tag, HalfWord cid, HalfWord count, Byte *buffer)

Append a Twrite onto a buf_stream. Sends Rerror if there is no room left in the buffer. Note that there is no mechanism for offset.

AppendReadRequest (buf_stream *st, Word session, HalfWord tag, HalfWord cid, HalfWord count)

Append a Tread onto a buf_stream. Sends Rerror if there is no room left in the buffer. Note that there is no mechanism for offset.

RemoveRequest (Word session, HalfWord tag, HalfWord how)

Search through all buf_streams for Twrite or Tread requests matching tag. Removes the requests from their associated buf_streams and sends Rread, Rwrite, or no response in accordance with how:


#define BUF_ABORT	0	/* how parameter of RemoveRequest*/
#define BUF_FLUSH	1	/* how parameter of RemoveRequest*/

Note that the buf_stream is not specified in this function. All buf_streams are searched for requests (there should be no more than one) matching session and tag.

Internally, a hash table is used to locate requests quickly by their tag.

Halfword BytesPending (buf_stream *st)

Return the number of bytes available for Xfer in a read or write stream.

XferStrStr (buf_stream *st_write, buf_stream *st_read, HalfWord count)

Transfer count bytes of data from a write stream to a read stream. Sends Rread upon completing each Tread in the read buf_stream.

XferStrBuf (buf_stream *st_write, Byte *buffer, HalfWord count)

Transfer count bytes of data from a write stream to buffer. The size of the buffer is not checked before copying data into it.

XferBufStr (buf_stream *st_read, Byte *buffer, HalfWord count)

Transfer count bytes of data from buf to a read stream. Sends Rread upon completing each Tread in the read buf_stream.


How to use this library in your server code

  1. Check #DEFINES in srvr-params.h
    /* Size of each request buffer for blocking i/o */
    
    #define REQ_BUFSZ 4096
    
    /* Number of global request buffers */
    
    #define REQ_BUFS 128
    
    
  2. Include srvr_buf.h in the server code
  3. Declare your streams in the server code. For example, in a pipe server we might see:
    
    buf_stream my_test_pipe_stream[2];
    
    
    Where my_test_pipe_stream[0] would be used as the Tread stream and my_test_pipe_stream[1] would be used as the Twrite stream.


Mike Berry <berrym@eros-os.org>

Copyright 1998 by Jonathan Shapiro. All rights reserved. For terms of redistribution, see the GNU General Public License