\chapter{Component Configurators}
\label{chap:comp-config}
\index{component configurator|(textbf}

As explained in Section \ref{sec:comp-config}, component configurators are
responsible for holding information about the dynamic inter-component
dependencies at runtime and implementing reconfiguration policies. 

We begin this chapter by stressing the benefits of this model in 
achieving a clear separation of concerns. Next, we describe concrete
implementations of component configurators in C++, Java, and CORBA.
Finally, we discuss customization of component configurators.

\section{Separation of Concerns}
\index{separation of concerns|(}
\index{reflection|textbf}
\index{meta-objects|see{reflection}}

By combining the ideas of computational reflection \cite{smith84:reflection} and
object-orientation, Kiczales created the concept of the \emph{meta-object protocol}
\cite{kiczales91:clos}. In his model, the programming language can be modified
and extended by the user, who becomes a partner in language design. The
protocol makes a distinction between base-level and meta-level objects. It
uses meta-level objects, or \emph{meta-objects}, to specify the behavior of the basic
language operations and constructs. If the user does not alter the meta-level,
the default meta-objects are used and the language is not altered. However, if the
user specializes the meta-objects by using object-oriented inheritance, then
the language behavior changes and can be customized to the application. 

The meta-object protocol allows for a clean \emph{separation of concerns} in the
implementation of non-functional aspects of base-level objects. Aspects such as
persistence, replication, and reconfiguration can be addressed by the
meta-objects while the basic application objects are not modified.

Although this is an extremely flexible model that allows for a clean
separation of concerns, previous implementations led to significant
performance degradations since every method invocation to an object was
intercepted by its meta-object.

Kramer introduced the concept of \emph{configuration
programming}\index{configuration programming}
\cite{kramer90:configuration-programming}, claiming that, to construct and
manage distributed applications in a clean and effective way, it is necessary
to adopt a \emph{configuration language} independent of the component
\emph{implementation language}. He argued that the code for configuration
should be separated from the component code.

Instead of relying on a different configuration language such as Darwin
\cite{darwin:regis94,darwin:corba97}, this thesis proposes a novel model
in which the basic functionality of the configuration engine is exported
through a well-defined interface\footnote{We define the configuration
interfaces in C++ using abstract classes, in Java using the \texttt{interface}
keyword, and in CORBA using OMG IDL.}. The actual configuration code is
written in any language the developer chooses and is encapsulated in the
component configurators. The latter can be reused in different contexts, but
they can also be customized to each situation.

Using reflection\index{reflection} terminology, component configurators
are meta-objects, but with the advantage that their code is only executed when
(re)configuration is required. They do not intercept every method call and,
therefore, do not degrade application performance.

Our model is better suited for the highly heterogeneous environments of the
future since the configuration engine can be defined using OMG IDL and then
accessed, via CORBA, from any platform, using any programming
language. Besides, the dynamic dependencies are accessible at runtime and,
unlike in conventional configuration languages, can be inspected and modified
at any time.

\index{separation of concerns|)}

\section{Implementation}

Component configurators are normally dormant until they receive a request for
reconfiguration or some other event notification. However, if the application
developer desires, a certain component configurator can be active and have its
own thread of execution. In this case, it could, for example, monitor system
activity and send requests and event notifications to other configurators and
components.

Depending on the way it is implemented, a component configurator is capable of
referring to components running on a single address space, on different
address spaces and processes, or even running on different machines in a
distributed system.

First, we describe a C++ implementation for a single address space. Next, we
describe a Java implementation that was initially designed for a single
address space but later extended to distributed systems using Java
RMI. Finally, we describe a CORBA implementation for distributed systems.

\subsection{C++}
\index{component configurator!C++}

Figure \ref{fig:comp-config} contains a simplified
declaration\footnote{Complete implementations of the component configurator
framework in C++, Java, and CORBA are available at
\url{http://choices.cs.uiuc.edu/2k/ComponentConfigurator}.} of a
\class{ComponentConfigurator} base class in C++. Figure
\ref{fig:method-calls} shows a schematic representation of some of its method
calls.

\begin{figure}[htbp]
\begin{center}
{\small
\begin{boxedverbatim}
class ComponentConfigurator {
public:
 ComponentConfigurator(Object *implementation);
 ~ComponentConfigurator ();

 int addHook          (const char *hookName);
 int deleteHook       (const char *hookName);
 int hook             (const char *hookName, ComponentConfigurator *component);
 int unhook           (const char *hookName);
 int registerClient   (ComponentConfigurator *client, const char *hookNameInClient=NULL);
 int unregisterClient (ComponentConfigurator *client);
 
 int eventFromHookedComponent (ComponentConfigurator *hookedComponent, Event e);
 int eventFromClient          (ComponentConfigurator *client, Event e);
 
 char *name ();
 char *info ();
 DependencyList *listHooks ();
 DependencyList *listClients ();
 ComponentConfigurator *getHookedComponent (const char *hookName);

 Object *implementation ();
}
\end{boxedverbatim}
}
\end{center}
    \caption{The \class{ComponentConfigurator} C++ Base Class}
    \label{fig:comp-config}
\end{figure}

\begin{figure}[htbp]
  \begin{center}
    \leavevmode \epsfig{file=figs/methodCalls.eps,width=12cm}
    \caption{Methods for Specifying Dependencies and Sending Events}
    \label{fig:method-calls}
  \end{center}
\end{figure}

The class constructor receives a pointer to the component implementation as a
parameter. It can be later obtained through the \method{implementation()}
method.

The \method{addHook()} and \method{deleteHook()} methods are used to create
and remove component configurator hooks. Each hook is identified by a
string, representing its name.\index{hooks}

The \method{hook()} method is used to specify that this component depends upon
another component and \method{unhook()} breaks this
dependence.\index{dependence management} The \method{registerClient()} and
\method{unregisterClient()} methods are similar to \method{hook()} and
\method{unhook()} but they specify that other components (called clients)
depend upon this component.

\method{eventFromHookedComponent()} announces that a component which is attached
to this component has sent an event. The \class{ComponentConfigurator()}
class is subclassed to implement different behaviors when events are
reported. Examples of common events are the destruction of a hooked component,
the internal reconfiguration of a hooked component, or the replacement of the
implementation of a hooked component.

\method{eventFromClient()} is similar to the previous method but it announces
that a client has sent an event. This can be used, for example, to trigger
reconfigurations in a component to adapt to new conditions in its clients.
Our reference implementation defines a basic set of events including
\class{STARTED}, \class{FINISHED}, \class{SHUTDOWN}, \class{RECOVERED},
\class{RECONFIGURED}, \class{REPLACED}, \class{MIGRATED}, \class{DELETED}, 
and \class{FAILED}. Applications can extend this set by defining their own
events.

\method{name()} returns a pointer to a string containing the name of the
component and \method{info()} returns a pointer to a string containing a
description of the component. Specific \method{info()} implementations can
return different kinds of information like a list of configuration options
accepted by the component, or a URL for its documentation and source code.

\method{listHooks()} returns a pointer to a list of 
\class{DependencySpecification}s. A \class{DependencySpecification} is a
structure defined as
\begin{center}
\begin{boxedverbatim}
struct DependencySpecification {
 const char *hookName;
 ComponentConfigurator *component;
};
\end{boxedverbatim}
\end{center}

\method{listClients()} returns a pointer to a list of 
\class{DependencySpecification}s corresponding to the components that depend
on this component (its clients) and the name of the hooks (in the client's
\class{ComponentConfigurator}) to which this component is attached.

Finally, \method{getHookedComponent()} returns a pointer to the configurator
of the component that is attached to a given hook.

\subsection{Java}
\index{component configurator!Java}

The Java implementation is very similar to the C++ one. Its declaration as a Java
interface is shown in Figure \ref{fig:comp-config-java}.
\begin{figure}[htbp]
\begin{center}
{\small
\begin{boxedverbatim}
public interface ComponentConfigurator {

  public void destroyComponentConfigurator ();
  public void addHook (String hookName) throws ElementExists;
    
  public void deleteHook (String hookName) throws NotFound;
  public void hook (String hookName, ComponentConfigurator cc) 
     throws HookBusy, NotFound;
  public void unhook (String hookName)
     throws HookVacant, NotFound;

  public void registerClient (ComponentConfigurator client, 
                              String hookNameInClient)
     throws ElementExists;

  public void unregisterClient (ComponentConfigurator client, 
                                String hookNameInClient)
     throws NotFound;

  public void eventFromHookedComponent (ComponentConfigurator hookedComponent,
                                        ComponentEvent e);

  public void eventFromClient (ComponentConfigurator client,
                               ComponentEvent e);

  public String name ();
  public String info ();
  public Vector listHooks ();
  public Vector listClients ();
  public void name (String s);
  public void info (String s);
};
\end{boxedverbatim}
}
\end{center}
    \caption{The \class{ComponentConfigurator} Java Interface}
    \label{fig:comp-config-java}
\end{figure}
There are two minor differences with respect to the C++ version. The first is
the \method{destroyComponentConfigurator()} method. Unlike C++, Java does not have
explicit destructors. So, instead of calling the \method{delete} operator, as
done in C++, Java programmers can request a component configurator to release
its resources and prepare for its destruction by calling the 
\method{destroyComponentConfigurator()} method. Concrete implementations of
the \class{ComponentConfigurator} interface can also choose to call this
method on their implementation of the \class{finalize ()} method, which is
called by the JVM garbage collector.

The second difference is the addition of exceptions. When we first implemented
the C++ \class{ComponentConfigurator}, not every C++ compiler supported
exceptions properly\footnote{Nowadays, all major C++ compilers do support
exceptions.}. The C++ compilers that do support exceptions, generate a
considerably larger code when exceptions are used, which may be undesirable for
small devices with limited memory. So, we decided not to add them to the base
C++ class. Java compilers and virtual machines always support exceptions, so
our Java \class{ComponentConfigurator} uses them.

\subsection{CORBA}
\index{component configurator!CORBA}

In CORBA, the ComponentConfigurator interface is defined using OMG IDL.
Figure \ref{fig:comp-config-idl} shows a complete definition of the
\class{Configuration} module which includes the \class{ComponentConfigurator}
interface, definitions of dependencies and type structures, and a
\class{Factory} interface. 
\begin{figure}[htbp]
\begin{center}
{\footnotesize
\begin{boxedverbatim}
module Configuration 
{
  enum EventType {STARTED, FINISHED, SHUTDOWN, RECOVERED, RECONFIGURED, REPLACED,
                  MIGRATED, DELETED, FAILED, APP_SPECIFIC, UNKNOWN};
  struct Event
  {
    EventType type;
    string description;
  };
  interface ComponentConfigurator; // forward declaration
  struct DependencySpecification
  {
    string name;
    ComponentConfigurator componentConfig;
  };
  typedef sequence<DependencySpecification> DependencyList;     

  interface ComponentConfigurator
    {
      exception invalidArgument{};
      exception ElementExists{};
      exception NotFound{};
      exception HookBusy{};
      exception HookVacant{};
      
      void destroy ();
      void addHook          (in string hookName) raises (ElementExists);
      void deleteHook       (in string hookName) raises (NotFound);
      void hook             (in string hookName, in ComponentConfigurator cc) raises (NotFound);
      void unhook           (in string hookName) raises (HookVacant, NotFound);

      void registerClient   (in ComponentConfigurator client, 
                             in string hookNameInClient) raises (ElementExists);
      void unregisterClient (in ComponentConfigurator client, 
                             in string hookNameInClient) raises (NotFound);
      void eventFromHookedComponent (in ComponentConfigurator hookedComponent,
                                     in Event e, in unsigned short timeToLive);
      void eventFromClient          (in ComponentConfigurator client,
                                     in Event e, in unsigned short timeToLive);

      string name ();
      string info ();
      DependencyList listHooks ();
      ComponentConfigurator getHookedComponent(in string hookName);
      unsigned short numberOfClients ();
      DependencyList listClients ();
      Object implementation ();
    };

  interface Factory
    {
      ComponentConfigurator newConfigurator (in string name, in Object implementation);
      oneway void shutdown ();
    };
};
\end{boxedverbatim}
}
\end{center}
    \caption{The \class{Configuration} Module IDL interface}
    \label{fig:comp-config-idl}
\end{figure}
In this case, the interface can be implemented in any programming language and
different implementations can communicate with each other seamlessly. We
developed an implementation in C++ while other students in our department
(Jennifer Jackson and Steve Zelinka) developed a Java version using the ORB
that comes with the Java 1.2 distribution.

What is new here is the introduction of a factory for component
configurators. The factory is a CORBA server that is responsible for creating
component configurator objects that reside in the address-space in
which the factory is located. Depending on where the programmer chooses to
place the factories, the component configurators can be (1) co-located
with their respective component implementations, (2) located in a separate
process in the same machine or (3) located in a central node on the network
while the component implementations are distributed.  In all three cases, the
communication with the component configurators is done exactly in the same
way, via CORBA. No changes are required in the code to interact with local
or remote component configurators.

In the CORBA implementation, a \class{DependencySpecification}
stores a CORBA Interoperable Object Reference (IOR) so that the
component configurator is able to reify dependencies among distributed
components. 

When a CORBA component is destroyed, the component implementation (or the ORB)
must call the configurator destructor so that it can tell its clients that the
destruction is taking place.  If a node crashes or if the whole process
containing both the component and the configurator crash, it might not be
possible to execute the configurator destructor. In this case, the clients
will not be informed of the component destruction.  Subsequent CORBA
invocations to the crashed component will raise an exception announcing that
the object is not reachable or that it does not exist. This exception may be
caught by the client component, which would be responsible for locating a new
server component and updating its component configurator. Alternatively, the
exception could be caught by an interceptor installed in the ORB, which could
locate the new server and update the client configurator without the client's
knowledge.

\section{Customization}
\index{component configurator!customization}

Our infrastructure includes a basic component configurator that provides
simple implementations for the dependency management operations (e.g.,
\method{addHook(), registerClient()}) and a few subclasses implementing
additional functionality such as mutual-exclusion (see Section
\ref{sec:locking-configurator}).

Programmers can extend these basic classes in two ways. First, they can be
customized to provide some generic functionality that could be reused by
several applications in different contexts. This could include support for
persistence, security, replication, and so on. In Section
\ref{sec:cc-dynconf}, we discuss how to customize a component
configurator to support dynamic reconfiguration.

The second way of extending component configurators refers to
application-specific extensions. For example, the programmer of a
computationally-intensive distributed scientific application could include
code to monitor local CPU load in the component configurator. The
configurators, then, could exchange events with information about the CPU load
on their machines and implement an algorithm for dynamic load balancing. The
component would contain the code for carrying out the application task
(scientific computation) while the component configurator would encapsulate
the policies for load balancing.

We now discuss some examples of component configurator customization that
are particularly interesting.

\subsection{An Application-Specific Customization}

We present here a simple example of an application-specific customization. A
detailed example of a customization to support fault-tolerance in a QoS-sensitive
application is presented in Section \ref{sec:reflector}.

The dynamic dependence information enables the reconfiguration of components
that are already running. Although our infrastructure does not guarantee safe
reconfiguration by itself, it does provide a valuable framework for
programmers to implement safe reconfiguration more easily and uniformly.

Continuing with our web browser example (introduced in Section
\ref{sec:autoconfig-concrete}), the application developer could implement a
\class{WebBrowserConfigurator} by using inheritance from the
\class{ComponentConfigurator} class and customizing it to deal with the dynamic
replacement of the system's JVM. As shown in Figure~\ref{fig:web-config}, the
\method{eventFromHookedComponent} method can be overridden to catch
\class{REPLACED} events coming from the JVM \class{ComponentConfigurator}.


\begin{figure}[htbp]
\begin{center}
{\footnotesize
\begin{boxedverbatim}
int WebBrowserConfigurator::eventFromHookedComponent (ComponentConfigurator *cc, Event e) 
{
 if (cc == JVMConfigurator)
  {
   if (e == REPLACED)
    try {   
     FrozenObjs fo = currentJVM->freezeAllObjs ();
     currentJVM = JVMConfigurator->implementation ();
     currentJVM->meltObjects (fo);
    }
    catch (Exception exp)
      throw ReconfigurationFailed(exp); 
  }
 else ...
}
\end{boxedverbatim}
}
\end{center}
    \caption{Customization of the \method{eventFromHookedComponent} Method}
    \label{fig:web-config}
\end{figure}

When the implementation of the JVM is updated, the
\class{JVMConfigurator} sends a \class{REPLACED} event to its clients. When
the \class{WebBrowserConfigurator} receives this event, it freezes all the
objects in the current JVM (using the Java object serialization mechanism),
updates the current JVM with the new JVM implementation, and melts the objects
in the new JVM\footnote{Since the Java serialization mechanism does not record
thread execution state, this must be performed with mechanisms like the ones
presented in
\cite{Bouchenak99b:capturing-java-thread-state,Bouchenak99:capturing-java-thread-state}
and \cite{funfroken98:capturing-java-state}.}.

\subsection{Locking Configurator}
\label{sec:locking-configurator}

The most basic version of the C++ component configurator we implemented is
called \class{SimpleConfigurator}. It does not provide any support for
controlling concurrent accesses to the configurator by multiple threads. To
support that, we implemented a subclass called \class{LockingConfigurator}.

\class{LockingConfigurator} uses two locks. The first controls read 
and write accesses to the dependencies and the second, to the component
implementation. Both permit either multiple concurrent readers (and no writers)
or a single writer. 

The \method{listHooks()} method, for example, is implemented by first
acquiring the dependencies lock in reading mode, then calling the equivalent
method in the super class, and then releasing the lock.

\begin{center}
{\small
\begin{boxedverbatim}
 inline DependencyList *listHooks ()
    {
      dependenciesLock_.acquire_read();
      DependencyList *ret = SimpleConfigurator::listHooks();
      dependenciesLock_.release ();
      return ret;
    }
\end{boxedverbatim}
}
\end{center}

The \method{registerClient()} method, on the other hand, acquires the lock in 
writing mode. 

\begin{center}
{\small
\begin{boxedverbatim}
 inline int registerClient (ComponentConfigurator *client, const char *hookNameInClient)
   {
     dependenciesLock_.acquire_write();
     int ret = SimpleConfigurator::registerClient(client, hookNameInClient);
     dependenciesLock_.release ();
     return ret;
   }
\end{boxedverbatim}
}
\end{center}

The \method{implementationLock} can be obtained through an accessor method. In
that way, programmers can lock the implementation of a component and be sure that
it will not change while it is locked.

\subsection{Dependency Attributes}
\index{dependency attributes|(}
\index{attributes|see{dependency attributes}}

After some experience with the configurators, we noticed that, in some
applications, it is desirable to assign attributes to dependencies. In that
way, we can have different types of dependencies.  Dependency attributes can
also be used to store more information about the characteristics of that
dependency. Developers can program policies that treat dependencies
differently based on their attributes.

Consider, for example, a File Server that has two types of clients. The first
are simple client programs activated by users. The second are backup storage
devices that simply read everything from the File Server from time to time,
saving its contents into tape. When the File Server is shut down by the
administrator, its configurator may need to send an event to the backup
devices so that its content can be copied. In this case, the shut down process
should be delayed until all the server contents is backed up to tape. By using
attributes, the File Server configurator can differentiate between the clients
that need to be notified synchronously (backup devices) and clients that do
not need to be notified (user programs).

Figure \ref{fig:comp-config-attributes} shows the Java
\class{ComponentConfiguratorAttrib} interface that inherits from the basic 
\class{ComponentConfigurator} interface, adding support for attributes. 
\class{DependencyAttributes} is a list of attributes; each attribute is
defined as a $<$\class{name,value}$>$ pair, where \class{name} is a string and
\class{value} is any Java object.

\begin{figure}[htbp]
\begin{center}
{\small
\begin{boxedverbatim}
public interface ComponentConfiguratorAttrib extends ComponentConfigurator 
 {
  public void addHook (String hookName, DependencyAttributes attributes) 
    throws ElementExists;
        
  public void hook (String hookName, ComponentConfigurator cc, 
                    DependencyAttributes attributes) 
    throws HookBusy, NotFound;
    
  public void registerClient (ComponentConfigurator client, String hookNameInClient,
                              DependencyAttributes attributes)
    throws ElementExists;
 };
\end{boxedverbatim}
}
\end{center}
    \caption{The \class{ComponentConfiguratorAttrib} Interface Supporting Attributes}
    \label{fig:comp-config-attributes}
\end{figure}

Our implementation of the \class{ComponentConfiguratorAttrib} interface was
used in a decentralized information system \cite{wcsf00:sidam} described in
Section \ref{sec:cc-use-cases}.

\index{dependency attributes|)}

%\subsection{Storing Alternatives}
%SE SOBRAR TEMPO


\subsection{Supporting Consistent Dynamic Reconfiguration}
\label{sec:cc-dynconf}
\index{consistency|textbf}

In a general sense, when replacing an old component by a new one it may be
necessary to transfer the state from the former to the latter. This process
can be automated by the reconfiguration engine by requiring every
component to implement a pair of operations \method{get\_state()} and
\method{set\_state()}.  All the components of a certain type must then
agree on a common external representation for the state of the components of
that type. Then, the underlying engine simply transfers the state from
one component to the other, without having to interpret its meaning.

To replace a component and remove the old version safely, one must make sure
that no other component will try to contact the component being removed. This
can be achieved by using a combination of the following four mechanisms.
\begin{enumerate}
\item Using the \class{ComponentConfigurator} to notify all the components that have a
reference to the old one.

\item Using the \class{ComponentConfigurator} as an
indirection on calls to replaceable components.

\item Leaving a forwarding pointer in place of the old component.

\item Making every access to the old component throw an exception to be
captured by the client. In this case, the client gets a reference to the new
component by contacting a third party such as the Naming Service.

\item Keeping the old versions accessible to old client components and
redirecting new clients to the new version. When the reference count in the
old version reaches zero, it can be removed safely.
\end{enumerate}

It is possible to implement these mechanisms in a specialized subclass of the
\class{ComponentConfigurator}. This can be achieved with an implementation of
the ideas that Bloom and Day discuss in \cite{argus93}, providing a more
sophisticated support for dynamic reconfiguration at the middleware level and
requiring less application participation.  Different combinations of these
mechanisms can be used in different parts of a single system.


\section{Use Cases}
\label{sec:cc-use-cases}
\index{component configurator!use cases}

The \class{ComponentConfigurator} model described in this chapter has been
deployed in the following systems.

\begin{enumerate}
\item \dTAO uses the model to represent the dependencies among the internal
components of a CORBA ORB and support dynamic reconfiguration (see
\cite{kon00:dtao} and Section \ref{sec:dtao}).

\item SIDAM\index{SIDAM}, a decentralized information system for disseminating
road traffic information using mobile agents \cite{SIDAM-SEMISH98}. In this
system, Menezes used customized component configurators to manage dynamic
configuration of \texttt{LocatorServers} implemented using Java RMI. In this
system, the \texttt{LocatorServers} objects are responsible for telling
clients where they should get their information. When \texttt{LocatorServers}
are removed from the system, the component configurators act to reconfigure
the system automatically to maintain consistency\index{consistency}.

According to experimental results, the use of the component configurator for
dependence management\index{dependence management!overhead} in this system
imposes an overhead of 10\% at initialization time. After the initialization
is completed, the component configurators only act when reconfiguration is
required and, therefore, impose no overhead during normal system execution
\cite{wcsf00:sidam}.

\item A CORBA Persistent Object Service implemented by Arjun Iyer as a Masters
project \cite{arjunMS}. Iyer used component configurators to represent the
dependencies among his \texttt{DataStore}, \texttt{PersistentDataStore},
\texttt{PersistentObjectManager}, and  \texttt{PersistentObject} components.
Although Iyer did not implement support for dynamic reconfiguration and
fault-tolerance, his thesis discusses some of the issues involved in
implementing these functionalities with the component configurators.

\item A Distributed Chess\index{chess} game implemented by Colin Jones
as a class project for CS423. The CORBA component configurators were used to
manage the dependencies among the different components of the system: robot
players, human players, game observers, game logger, and the central chess
server.
\end{enumerate}

In addition to the completed systems described above, our 
model is being deployed in the following ongoing projects.

\begin{enumerate}
\item LegORB\index{LegORB}, a component-based CORBA ORB \cite{roman:legorb:00}
targeted at embedded systems and devices with little resources. In
contrast to full ORB implementations that require, typically, a few
megabytes of memory, LegORB loads only the minimal set of
components required to provide the functionality required by each
application. A minimal LegORB configuration using component configurators to
manage dynamic reconfiguration requires less than 150 Kbytes of memory.

\item A system for managing network-centric\index{network-centrism} user 
environments\index{environments} for the \twoK operating system
\cite{carvalho00:environments}. The model is used to keep references to user
applications in the distributed system, managing them properly.
\end{enumerate}

\index{component configurator|)}