Check out the new USENIX Web site. next up previous
Next: Services Up: Drivers Previous: Drivers


Type-based Composition

The composability of CANS components (both drivers and services) is decided by compatibility of the type information associated with the input and output ports being connected. The types used in CANS integrate two closely related concepts: data types and stream types. CANS data types are the basic unit of type information, represented by a type object that in addition to a unique type name can contain arbitrary attributes and operations for checking type compatibility. Traditional mechanisms such as type hierarchies can still be used to organize data types; however, our scheme permits flexible type compatibility relationships not easily expressibly just by matching type names. For instance, it is possible to define a CANS type for MPEG data, which contains attributes for defining the frame size. An MPEG type can be defined compatible with another MPEG type as long as the former's frame size is smaller than the latter's, naturally capturing the behavior that a lower resolution MPEG stream can be played on a client platform capable of displaying a higher resolution stream. CANS stream types capture the aggregate effect of multiple CANS drivers operating upon a typed data stream. Stream types are constructed at run time, and representable as a stack of data types. Operations allowed on stream types include push, pop, peek, and clone, which have the standard meanings. Each CANS component with $m$ input ports and $n$ output ports defines a function, which maps its input stream types into output stream types:

\begin{displaymath}f(T_{in_{1}},T_{in_{2}},...,T_{in_{m}})\rightarrow(T_{out_{1}},
T_{out_{2}},...,T_{out_{n}})\end{displaymath}

where $T_{in_{i}}$ is the required stream type set for the $i$th input port, and $T_{out_{j}}$ is the resulting stream type produced on the $j$th output port. The type compatibility between an input and an output port, which determines whether two components can be connected, is determined by checking the top of the output port's stream type against the required data type of the input port. Stream type information flows downstream automatically when two ports get connected at run time. Figure 3 shows an example of the type compatibility scheme. The source produces MPEG data at resolution $500 \times 200$, which needs to be supplied to the sink that can consume MPEG data at resolution $512 \times 256$ after going through two components that respectively encrypt and decrypt the data. The figure shows the data types on each of the ports as well as the stream types on the connections. To consider an example, the Encryption driver accepts data type BaseStream and pushes an Encrypted type object onto the incoming stream type. The output port of Src is compatible with the input port of Encryption because the MPEG type object extends the BaseStream type. Similarly, the output port of Decryption, whose affect is to pop the Encrypted type from its incoming stream type, is compatible with the input port of Sink because of a type-specific compatibility operator for the MPEG type that looks at the resolution attributes. Figure 3 also highlights the composition advantages of representing stream types as a stack of data types. If components were just modeled as consuming data of a particular type and producing data of another type, it would be difficult to express the behavior of the Encryption and Decryption drivers in a way that permits their use for a variety of generic stream types without losing information about the original stream type at the output of the Decryption driver. Thus, determining whether the Decryption driver's output port is compatible with the input port on Sink would require examining the entire data path. In contrast, our stream type representation permits local decision making, a prerequisite for run-time adaptation via dynamic component composition.
next up previous
Next: Services Up: Drivers Previous: Drivers
Weisong Shi 2001-01-08