• 沒有找到結果。

Component Programming

2. Related Work

3.2 Component Programming

3.2.1 Component Definition and Component Communication

A component is a Java class. A protocol implementation, such as a TCP implementation, can be modeled as a single or multiple components. Each component instance is a Java object and the programmer can create multiple instances of a component during runtime. A protocol must be able to communicate with adjacent protocols on the same stack. For example, the TCP must be able to communicate with IP. Therefore, the components can communicate with each other via Java interfaces. A Java interface is a class that defines only the prototype of methods and does not provide an actual implementation. The actual implementation can be provided by a class that implements the methods of the interface.

Two components can be connected when one component implements an interface and the other holds a reference of that interface. A component that holds the interface reference can therefore invoke methods defined in the interface. The objective of interface and implementation is similar to provide and require constructs of languages that support dynamic reconfiguration (Kramer and Magee 1985; Magee et al. 1993).

Component instances are connected during runtime, either by the startup program or by the reconfiguration program. However, during component design time, a component must provide a set of link methods to store the interface references it holds. Thus, the startup

program or reconfiguration program can link two component instances by invoking the corresponding link methods. This technique is popular in designing object-oriented protocol stacks (Ananthaswamy 1995; Buschmann et al. 1996; Krupczak et al. 1998).

In order to identify the component instance to be reconfigured, each component instance must have a unique name. The unique name is given as an argument of the create operation and stored in the name field of each component. When invoking the create operation, the startup program or the reconfiguration program must determine the unique name. Unique name helps subsequent reconfiguration programs to address component instances without ambiguity. Component instances are identified by unique names instead of component names because a component may have multiple instances.

3.2.2 External Interfaces

Components can interact with the user application or the network device through special interfaces defined by the component framework, as shown in Figure 3-3. A component that wishes to interact with the user application must implement the SocketDown interface and have a reference to the SocketUp interface. The SocketDown interface defines the

Figure 3-3: Service interfaces defined by the component framework.

Component

SocketDown SocketUp

Component

DeviceDown DeviceUp Component Framework

following methods: create, connect, bind, listen, accept, sendmsg, and close.

The SocketUp interface defines the accept_callback and receive_callback methods. Likewise, a component wishes to interact with the network device must implement the DeviceUp interface and have a reference to the DeviceDown interface. The DeviceDown interface defines the output method and the DeviceUp interface defines the input method.

3.2.3 Component Execution Model

The component framework adopts a passive component execution model in which each component is passive. A passive component is not bound with a thread, so it is invoked only by the threads owned by the user application or by the component framework. In addition, a component cannot have an infinite loop. That is, each component method must return in a reasonable time.

We choose the passive execution model for two reasons. First, the passive model is usually used by protocol implementations of operating system kernels, such as the TCP/IP implementation of the Linux kernel. Second, the passive model is also used to obtain the safe reconfiguration point, which is discussed later.

3.2.4 Component States

During component replacement, the state of the old component instance is transferred to the new instance. Thus, the component state must be defined before the state transfer. For ease of programming, the component framework treats object states as component states. The component states can therefore be transferred by the standard Java object persistence mechanism, the Java serialization (Sun Microsystems 2001), which is provided by almost every Java virtual machine.

The Java serialization is used to store the state of a living object in the storage and reconstruct it from the storage later. The programming aspect of the Java serialization can be found in (Arnold et al. 2000). When designing a component, the programmer must declare it as Serializable so that it can be accessed by the Java serialization. Thus, the reconfiguration management subsystem can use the Java serialization to automatically transfer the component state. This approach does not need any proprietary state transfer code written by the programmer.

The other benefit of this approach is that if some fields are not considered as part of the component state, the programmer can declare these fields as transient. Transient is a keyword of the Java language and transient fields will be discarded during serialization. Note that the fields referring to other components must be declared as transient because they are not part of the component state.

3.2.5 User-defined Handlers

Although the component states can be automatically transferred by the component framework, the default state transfer mechanism may not satisfy all of the components. For example, if the new component defines a field that is not present in the old component, the default mechanism will not have sufficient knowledge to determine the suitable value of this field. In such case, the programmer can provide a user-defined handler, which is invoked after the default state transfer. In order to transfer these inconsistent fields, the user-defined handler is allowed to use Java reflection (Sun Microsystems 1997) to inspect and set their values. The Java reflection is a virtual machine feature together with a set of libraries that can inspect the structure and modify the content of objects during runtime. The programming of Java reflection can be found in (Arnold et al. 2000).

3.2.6 A Protocol Component Example

A simple component example is shown in Figure 3-4. ComponentA is a component that connects to the lower part of the component framework, so it implements the DeviceUp interface and holds a reference of the DeviceDown interface. Since DeviceUp defines the input method, it is implemented by ComponentA. The field name stores the unique name given by the startup program or the reconfiguration program. The method setDeviceDown is a link method that stores the reference of DeviceDown to the field dd. The dd field is a transient field because component references do not belong to the component state of ComponentA. ComponentA is declared as Serializable because it has to be used by Java serialization during replacement. Note that a component does not have to inherit from a component base class because we focus on component-based programming rather than object-oriented programming, and a base class is not really necessary for our component framework.

public class ComponentA implements DeviceUp, Serializable { String name;

transient DeviceDown dd;

...

public void setDeviceDown(DeviceDown d) { dd=d;

Figure 3-4: A protocol component example.

public interface DeviceUp { public void input(…);

}

3.3 Implementation of the Component

相關文件