Home

Traffic Server Software Developers Kit

Chapter 15. IO Guide

Table of Contents

Vconnections
The vconnection user’s view
Net Vconnections
Transformations
The Vconnection Implementor’s View
Transformation VConnection
VIOs
IO Buffers
Guide to the Cache API
How to Do a Cache Read
How to Do a Cache Write
How to Do a Cache Remove
Errors
Example

This chapter contains the following sections:

Vconnections

The vconnection user’s view

To use a vconnection, a user first needs to get a handle to one. This is usually accomplished by having it handed to the user or by the user issuing a call that creates a vconnection (such as INKNetConnect). In the case of transform plugins, the plugin creates a transformation vconnection using INKTransformCreate and then accesses the output vconnection using INKTransformOutputVConnGet.

Once the user has a handle to a vconnection, she can then issue a read or write call. It’s important to note that not all vconnections support both reading and writing - as of yet, there has not been a need to query a vconnection as to whether it can perform a read or write operation. That ability is obvious from context.

To issue a read or write operation, a user calls INKVConnRead or INKVConnWrite. These two operations both return VIO (INKVIO). The VIO describes the operation being performed and how much progress has been made. Transform plugins initiate output to the downstream vconnection by calling INKVConnWrite.

A vconnection read or write operation is different from a normal UNIX read(2) or write(2) operation. Specifically, the vconnection operation can specify more data to be read or written than exists in the buffer handed to the operation. For example, it's typical to issue a read for INT_MAX (4 billion) bytes from a network vconnection in order to read all the data from the network connection until the end of stream is reached. This contrasts with the usual UNIX fashion of issuing repeated calls to read(2), until one of the calls finally returns 0 to indicate the end of stream was reached (indeed, the underlying implementation of vconnections on UNIX still does issue those calls to read(2), but the interface does not expose that detail).

A given vconnection can have at most one read operation and one write operation being performed on it. This is restricted both by design and common sense: if two write operations were to be performed on a single vconnection, then the user would not be able to specify which should occur first and the output would occur in an intermingled fashion. Note that both a read operation and a write operation can happen on a single vconnection at the same time; the restriction is on more than one operation of a given type.

One obvious issue is that the buffer passed to INKVConnRead and INKVConnWrite won’t be large enough - there is no reasonable way to make a buffer that can hold INT_MAX (4 billion) bytes. The secret is that vconnections engage in a protocol whereby they signal to the user (the continuation passed to INKVConnRead and INKVConnWrite) that they have emptied the buffers passed to them and are ready for more data. When this occurs, it is up to the user to add more data to the buffers (or wait for more data to be added) and then wake up the vconnection by calling INKVIOReenable on the VIO describing the operation. INKVIOReenable specifies that the buffer for the operation has been modified and that the vconnection should reexamine it to see if it can make further progress.

The null transform plugin provides an example of how this is done. Below is a prototype for INKVConnWrite:

INKVIO INKVConnWrite (INKVConn connp, INKCont contp, INKIOBufferReader readerp, int nbytes)

The connp is the vconnection the user is writing to and contp is the “user” – i.e., the continuation that connp calls back when it has emptied its buffer and is ready for more data.

The call made in the null transform plugin is:

INKVConnWrite (output_conn, contp, data->output_reader, INKVIONBytesGet (input_vio));

In the example above, contp is the transformation vconnection that is writing to the output vconnection. The number of bytes to be written is obtained from input_vio by INKVIONBytesGet.

When a vconnection calls back its user to indicate that it wants more data (or when some other condition has occurred), it issues a call to INKContCall. It passes the INKVIO describing the operation as the data parameter, and one of the values below as the event parameter.

Event Parameter Value Description
INK_EVENT_ERROR Indicates an error has occurred on the vconnection. This will happen for network IO if the underlying read(2) or write(2) call returns an error.
INK_EVENT_VCONN_READ_READY The vconnection has placed data in the buffer passed to an INKVConnRead operation and it would like to do more IO, but the buffer is now full. When the user consumes the data from the buffer, this should re-enable the VIO so it indicates to the vconnection that the buffer has been modified.
INK_EVENT_VCONN_WRITE_READY The vconnection has removed data from the buffer passed to an INKVConnWrite operation and it would like to do more IO, but the buffer does not have enough data in it. When placing more data in the buffer, the user should re-enable the VIO so it indicates to the vconnection that the buffer has been modified.
INK_EVENT_VCONN_READ_COMPLETE The vconnection has read all the bytes specified by an INKVConnRead operation. The vconnection can now be used to initiate a new IO operation.
INK_EVENT_VCONN_WRITE_COMPLETE The vconnection has written all the bytes specified by an INKVConnWrite operation. The vconnection can now be used to initiate a new IO operation.
INK_EVENT_VCONN_EOS An attempt was made to read past the end of the stream of bytes during the handling of an INKVConnRead operation. This event occurs when the number of bytes available for reading from a vconnection is less than the number of bytes the user specifies should be read from the vconnection in a call to INKVConnRead. A common case where this occurs is when the user specifies that INT_MAX bytes are to be read from a network connection.

For example: the null transform plugin’s transformation receives INK_EVENT_VCONN_WRITE_READY and INK_EVENT_VCONN_WRITE_COMPLETE events from the downstream vconnection as a result of the call to INKVConnWrite.

After using a vconnection, the user must call INKVConnClose or INKVConnAbort. While both calls indicate that the vconnection can destroy itself, INKVConnAbort should be used when the connection is being closed abnormally. After a call to INKVConnClose or INKVConnAbort, the user will not be called back by the vconnection again.

Sometimes it’s desirable to simply close down the write portion of a connection while keeping the read portion open. This can be accomplished via the INKVConnShutdown function, which shuts down either the read or write portion of a vconnection. Shutdown means that the vconnection will no longer call back the user with events for the portion of the connection that was shut down. For example: if the user shuts down the write portion of a connection, then the INK_EVENT_VCONN_WRITE_READY or INK_EVENT_VCONN_WRITE_COMPLETE events will not be produced. In the null transform plugin, the write operation is shut down with a call to INKVConnShutdown. To learn how vconnections are used in transformation plugins, see Writing Content Transform Plugins.

The vconnection functions are:

  • INKVConnAbort

  • INKVConnClose

  • INKVConnClosedGet (used for Transformations only)

  • INKVConnCreate

  • INKVConnRead

  • INKVConnReadVIOGet

  • INKVConnShutdown

  • INKVConnWrite

  • INKVConnWriteVIOGet