Olan: A Language and Runtime Support for Distributed Application Configuration L. Bellissard Bull-IMAG/Syste`mes 2, rue de Vignate 38610 Gie`res
[email protected]
Michel Riveill Universite´ de Savoie - LGIS Campus Scientifique 73370 Le Bourget du Lac
[email protected]
Abstract: This paper presents a component-based programming model whose goal is to make construction and management of distributed cooperative applications easier. The approach taken aims at combining Module Interconnection Language features with the concept of class derived from object-oriented models. Using our model, an application is seen as a hierarchy of interacting components, where a component represents the building unit for construction and management. Low level components contain objects or piece of software written in any programming language. The proposed model is being implemented on top of a distributed object-based platform that provides object distribution, object sharing and clustering.
1 Introduction This paper claims that the construction and the management of distributed cooperative applications would be facilitated by introducing the concept of class, as defined in object-oriented models, into Module Interconnection Languages. It proposes a component-based programming model, called OLAN to comply with this position. We define cooperative applications as applications involving several users working on a set of distributed workstations, sharing information and interacting in real time. Examples of such applications are teleconferencing, electronic diaries, software development environments and workflow applications. These applications may be considered as a set of interacting software entities (active or passive), that may be called agents [5][7]. For example, agents may represent the instances of an electronic diary application. The act of constructing such applications refers to the description of software entities involved, the definition of interactions between them and the evolution of these two sets throughout the lifetime of the application. The act of management deals with the accurate use of system resources according to application requirements, for instance placement of components on a distributed network, observation, access control. We submit that these two actions should be based on a single unifying model that brings together specific features not always available in current programming models, including object-oriented ones: 1. Interactions such as event broadcasting or service requests [5] between agents are cumbersome to express with a method-call or procedure-call facilities. 2. The possible interactions between agents may evolve during execution. For instance, an agent will accept to serve a given request at a given time and will refuse the following requests when it becomes busy. No support is provided to express this evolution. 3. The naming of agents, classically based on their identity or Oid, also appears as inconvenient because it is hard to predict which agents will be existing at a given time of execution and how they will interact :
1
user input make agents behave in an unpredictable way. There is a need for associative naming where agents are designated according to their properties and not to their name. 4. The usual granularity (object, module) for application construction and management is inadequate. It should be possible to define common interactions and to apply common rules of management to groups of agents. . Numerous projects address this field of software development and management. Polylith [11] supports the interconnections and reconfiguration of interactions between software units in heterogeneous environments. Durra [2] focuses on real-time application development. It allows the description of the dynamic evolution of interacting units. However, in both of these Module Interconnection Languages (MIL), software units are implementation derived and composition of objects is not directly supported, which from our point of view is essential for solving the above problem of granularity. Conic [8], and more recently Darwin/Regis [9] allows the structure of applications to be described in terms of components classes and interactions between them. They also provide management facilities for placement on an heterogeneous network. But they do not address the expression of aspects such as dynamic evolution and naming of components, which are specific to cooperative applications.
2 OLAN Component-based language An application whose configuration is described with OLAN, can be viewed as a hierarchy of interconnected component. Each level of the hierarchy is a separate OLAN description derived from a component class which encapsulate components - in fact component’s instance - contained in the next level. The leaves of the hierarchy are components with no OLAN description, they are called primitive component and encapsulate ’real’ piece of software, like C++ objects or C modules. They are derived from primitive component class. We have introduced the concepts of class and instance in a Module Interconnection Language to emphasize the distinction between the unit of reusability and encapsulation (the component class) and the effective unit at runtime (the component). 2.1
Component
As in object oriented programming language, component are described with an interface and an implementation. 2.1.1
Interface
The interface of a component class is made of information that help use the component without knowledge of its implementation. We have extended the usual concept of interface, as considered for example in the CORBA IDL, to include the description of all the properties required from a component to work properly. The interface is thereafter made of services, notifications[5] and attributes. Services Services are functions or procedures that can be executed or requested by a component. They are of two kinds: provided services are always offered by the implementation of a component class while required services are the services expected to be called by the implementation of the component class. Provided services are characterized by the obligation to fulfill any request while required services must always be supplied when connecting components together.
2
SharedApplication
component class SharedApplication { interface
Init;
provide Init; require SendOp (in string encodeOp, out int result);
SendOp (in string encodeOp, out int result);
provide ReceiveOp (in string encodeOp); ReceiveOp (in string encodeOp); attribute int ApplId; }
int ApplId;
Figure 1: A Component class interface Notifications and reactions Notifications and reactions are the pendant of required and provided services. Notifications are events whose broadcasting can trigger the execution of reaction on several components. Every component which receives a notification may decide whether to react to it or not : this is represented with Reactions. Notifications may or not be treated by the components corresponding reactions. Notifications are not to be always connected to a reaction. This is the intrinsic property that makes services and notification distinct from each other. Attributes Attributes are typed variables whose value is set at instantiation and can change during execution. The value of a given attribute can be imported from the implementation, set from outside of the component or modified by services or notifications broadcast and reception. The value of an attribute may also be forwarded from an attribute of a ’sub-component’. In that case, any update of the value is broadcasted everywhere the attribute is forwarded. In [4], we describe the construction with OLAN of a teleconferencing application. One of its goal is to make existing, single-user applications cooperate in a distributed multi-user environment with a WYSIWIS mode. Such applications are encapsulated in a component which interface is described in Fig. 1. The interface indicates that the SharedApplication component class provides an Init ’plug’and a receiveOp service which aims at reflecting on itself actions done on another shared application belonging to someone else. The required service aims at sending to other shared application actions performed on itself by its human owner. We provide both textual and graphical syntax. The graphical syntax is inspired from the Darwin configuration language, where boxes are components, white circles are required services, black circles are provided services, white squares are notifications and black squares are reactions. In the following sections, we use also lines to represent the interconnections between components and the interface. 2.1.2
Implementation
The implementation refers to what we introduced in the beginning of the section with the term hierarchy. A component class implementation is either made of ’sub-components’ or, referring to the leaves of the hierarchy, with ’real’ pieces of software. Primitive Component The primitive component class is the unit of encapsulation and reuse of existing code. Implementation of primitive component class is made of pieces of software that the programmer supplies. For instance, implementation could be composed of a set of C++ classes, a set of modules or libraries or any combination of them. Services provided at the interface level of the class must be supplied by the implementation. Attributes can be public variables of the implementation.
3
UserSession CoopControler
SharedApplication Launch
Init;
ReceiveOp
SendOp (in string encodeOp, out int result);
SendOp SendOp SendOp
ReceiveOp (in string encodeOp);
ReceiveOp ReceiveOp
int ApplId;
Figure 2: Composite component Composite Component The composite component class, commonly referred to as component class, is the unit of structuring the application. Its implementation is made of ’sub-components’ and interactions between them. ’Sub-components’ are instances of component class described elsewhere. Compared to usual programming language, the implementation defines which other components are needed and how they should communicate to achieve the interface rather than how functions of the interface are to be defined. Therefore, the implementation explicitly shows which sub-components are used and how they are interconnected. Still referring to the teleconferencing application, Fig. 2 is a component class that combines a Controller, that filters actions coming in and out of the SharedApplication and transmits the allowed actions to its ’super-component’. Roughly, this class represents the user in a collaborative session of the application. 2.2
Connector
Connectors are the units that mediate the interactions between components. Basically, they are the frames that enable ’lines’ to be drawn between several components inside an implementation (c.f Fig. 2 ). Connectors establish the rules that drive component interactions and specify the required protocol at runtime level. Rules at the connector level may be separated into: the kind of interface able to be connected (type compatibility between services,...), the protocols used for the effective communication (asynchronous vs. synchronous communication, event broadcast vs. remote procedure call,...), and the specification of an expected behavior and a set of constraints such as Qos requirements (e.g. for multimedia communication support). The connector description needs to define:
the kind of connector, that distinguishes the ones for interconnection purpose and the ones for the mapping of the interface with the implementation, the allowed source(s) of the communication, the allowed destination(s) of the communication, and the specification of the expected behavior, the constraints and the protocol. The concept of connector has already been introduces in the literature. In, connectors are specified using a subset of CSP process algebra to declare the expected behavior and the associated constraint. This, combined with the inclusion of some CSP specifications in the interface of components, allows compatibility checking between connectors and components. to be performed.
4
Existing Connector in OLAN The OLAN platform for now supports several kind of components. Their rules are still very simple and do not yet integrate constraint specifications. Actually, there is no language or formalism to express those connectors, they are build-in connectors provided by the runtime support and available in the OLAN language. Interaction Interactions are the effective communication that take place between such and such components. Interaction may be seen as "the instances" of a connector in a well defined context, i.e. in a specific implementation with its sources and destinations. Mapping with interface The mapping with the interface is the process of binding the interface requirements and provisions of the implementation. "Lines" drawn between a service - or notification/reaction and a sub-component, may be seen at execution time as a communication between the englobing component and sub-components. That’s why we use connectors here as well, as frame to build those links. component class UserInterface f // partial description interface provide ReceiveOp ( ); require SendOp ( ); implementation theCont = inst CoopControler; theAppl = inst SharedApplication; // mapping theCont.Launch bind to theAppl.Init using methodCall; theCont.SendOp bind to theAppl.ReceiveOp using methodCall; theAppl.SendOp bind to theCont.ReceiveOp using methodCall; g;
The description above is the textual syntax for the implementation of the UserSession component class (c.f Fig. 2). It shows the syntax for interactions and mapping ( statement bind to using ). The default connector for services binding is methodCall and broadcastEvent for notification, which explain the lack of using clause sometimes in the textual syntax. 2.3
Dynamic evolution
Until there, aspects described in the paper were only static aspects : instances of components are predefined before execution, interactions are set up once for ever,... Clearly, this is not satisfactory especially for application we aim at constructing. There is a need to enable and channel dynamic instantiation of component, to create sets of components and to have destinations of interactions and mapping evolve. Instantiation This is the act of describing the set of sub-component in an implementation. There is several ways of instantiating components, according to the time when it should be effectively created at runtime. The keyword inst refers to a predefined instance that is created as soon as the englobing component is created. To express more dynamicity, we also enable a component to be predefined in the class implementation but it will be really created the first time someone calls a service on it. This is the lazy instantiation scheme of Darwin. Collection Moreover, in order to facilitate handling of multiple component of a same component class, we introduce collections. A collection is a set of components which number at execution time is within a range defined by a minimum and a maximum cardinality. Collections allows the easy manipulation of a set of entities which can evolve dynamically and are accessed through their unified interface. As collection are
5
UserSession
theApplSet: [0..n]
CoopControler
SharedApplication Launch
Init;
ReceiveOp SendOp
SendOp (in string encodeOp, out int result);
SendOp SendOp
ReceiveOp
ReceiveOp (in string encodeOp);
ReceiveOp
int ApplId;
Figure 3: Instantiation and Collection supposed to be the keystone of dynamic instantiation, predefined services create and delete are provided in any collection. In addition, a special connector can operate as a creator of a new component of a collection before accessing the specified service. Associative Naming Introduction of collections raises new issues concerning naming of components. In a distributed system, objects are generally named with their object identifier (Oid). This naming scheme seems somehow restrictive and incompatible with collections, when the destination of a communication is a priori not known. Therefore, we are using associative naming facilities to distinguish the destination of an interaction (or a mapping). Associative naming is based on the existence and the runtime value of attributes. Among these attributes, one can always find for example, an object identifier, so a direct designation is still possible. However, in the case of collections, it is often more useful to define interaction destination with the help of more general and semantically richer attribute. component class UserInterface f // partial description interface provide ReceiveOp ( ); require SendOp ( ); implementation theCont = dyn inst CoopControler; theAppl = collection [0..n] of SharedApplication; // mapping theCont.Launch bind to theAppl.Init using createInCollection; theCont.SendOp bind to theAppl.ReceiveOp using methodCall where theApplSet.AppliId = applId; theAppl.SendOp bind to theCont.ReceiveOp using methodCall; g;
The syntax used is somewhat close to "where" clauses of SQL query language. 2.4
Management
Management of distributed applications is to adapt the application behavior to the underlying host environment. This is especially difficult because the same application may run on a variety of distributed architecture, ranging from one machine to tens or hundreds. Referring to [10], we can decompose Distributed Application Management into four points:
configuration of system components according available resources and application requirements,
6
deployment and initialization of the application in an orderly way, monitoring of application behavior and performance measurement, and tuning the application behavior according to monitored information. The goal of the OLAN component-based language is to ease the configuration process of a distributed application by providing the same programming model for software configuration (process dedicated to the application designer) and for management configuration (dedicated to the application administrator) which includes the first two points previously stated. Usually, adapting an application to specific environment needs such as varying workload on nodes, environment changes or failures,... requires re-programming and re-deploying part of the application. We would like to make the programming and management processes independent. Research activity has already focused on that area. Meta[10] provides a collection of tools that perform monitoring and control of the behavior of an application. The Meta system offers a control program, in charge of managing the application, clearly separated from the functional aspects. Defining this controller with Meta requires three steps:
instrumenting the application with sensors, that gather and monitor the desired information, and actuators that modify the behavior of application components, describing the application structure and the environment in which it runs with Lomita’s object-oriented data modelling facilities, and expressing the policy rules which describe the intended behavior of the system and can make direct calls to sensors and actuators. With OLAN, management facilities rely on the application structure and description already introduced. This description is the basis for configuration, deployment and installation of the application, as well as the setting up of instrumentation for further monitoring and tuning purposes.The following describes how instrumentation is achieved, and how it is used to define management policies that drive the application behavior. Management Interface In order to isolate management information from the rest of the definition of the component class, we introduce a special interface dedicated to management as well as a policy section that describes the instrumentation (sensors, actuators,...) used to achieve management activities[3], and their representative in the interface, the management attributes. This isolation into a particular interface prevents unallowed users to perform management actions. This approach tends to be common in distributed system management based on objects[12]. The management interface therefore contains a special kind of attribute, the management attributes. They can readable or writable, their value is collected from either system calls or from private variables of the implementation with the help of sensors. Attributes that are modified are able to react on the system with the help of actuators. This modification is done either by a human administrator with specific monitoring and tuning tools or by the management policies. Management Policies The management policies are in charge of the definition of:
the relation between management attributes and instrumentation, the relevant ’events’ supposed to change an attribute value, and
7
the reactions associated to a change of an attribute value. Each attribute has a set of associated policies. A policy is composed of a condition and a reaction triggered when the condition is fulfilled. Conditions may be either: predefined events, like the reading or modification of an attribute, the beginning or the end of a request on a service, or boolean condition based on testing of any attribute value. Reactions to such events may be of two kinds: changing the value of an attribute or using the instrumentation made of sensors or actuators. Each sensor and actuator are provided by the runtime support. They all have generic services attached to them, a read service for sensors and an activate service for actuators. We have not supplied an exhaustive definition of relevant events, neither have we a definite syntax for expressing the policies. The reader should refer [13] to for ideas about how to define such policies. Configuration of the Distribution Configuration for management purpose consists in setting particular attribute before an execution, as well as defining the policies that drive their utilization. So far, we have focused on one aspect of configuration: placement of components on a distributed system. Two management attribute are defined:
nodeName (string): it contains the effective name of the node on which the component is mapped. Associated with this attribute is a particular sensor called getHostNameSensor which returns the name of the sensor. This is a readonly attribute, its definition follows: management interface readonly attribute string nodeName; management policies nodeName:
f
on read do getHostNameSensor.read() polling = 0;
g;
The policy attached to the nodeName attribute means that when someone tries to read its value, a call to the predefined sensor is made. For each sensor, there is also an option that enables or disables continuous reading of sensors with a polling period. This is an interesting features because it allows attributes to be automatically updated - which may activate other policies upon their condition -.
nodeChoice (int): it contains an indication on the kind of node the component should be loaded when its creation or utilization is requested by the application. This attribute has no sensor attached to it but an actuator, called setHostChoiceActuator which asks the runtime to load the component on a node whose characteristics fit the given choice. management interface attribute int nodeChoice; management policies nodeChoice:
f
on instantiation do setHostChoiceActuator.activate (nodeChoice); on loading do setHostChoiceActuator.activate(nodeChoice);
g;
8
These policies react to predefined events which are, in this case, relevant when the component is either created (instantiation) or loaded for the first time (loading). The actuator is in charge of requesting the runtime for an adequate node which fulfills the nodeChoice value as one of its properties. Then the actuator transmits the name of the adequate node to the system that loads the component on the right node.
3 Experiments and Results We have recently achieved the construction of a teleconferencing application with the component-based language. As a matter of fact, this application named CoopScan[1], had its first prototypes build on Unix. Communication between nodes were realized with TCP or/and UDP sockets. The first step of our experimentation was to re-implement the application on top of Oode in order to appreciate the impact of object sharing and transparent distribution. The second step of the experimentation was to design the application as an interconnection of components, with a major constraint: reuse as much as possible the existing code. The experimentation on Unix had shown that communications programming with socket was quite a tough task, especially when the number of potential user of the application was supposed to be unlimited. The experimentation with Oode and distributed shared objects had decomplexified this task a lot. Communications are done through shared object which are accessible from any node in a transparent way. This is were the limitation of Oode lays: one goal of the CoopScan architecture was to build a fully distributed application with communication protocols between replicated object in order to lower network traffic. Oode transparent distribution and execution scheme let no real control of distribution. For instance, a shared distributed object is mapped on the node where it is first called. When another node wishes to access it, the execution flow must span on the node where the object is mapped in order to access it. There is no replication at all of objects between nodes. The experiment with OLAN had let us foreseen real progress in distributed application programming. The explicit structure of the application enables easy clustering of object functionally related, and then allows distribution of the clusters. Separation of the communication from the implementation had let us experiment different ways of communication between components. Above all, we have been able to create as many different kind or configuration of the application as we wanted to: an application with a shared editor allowing a maximum of two, three or n users, another application with a shared editor and a shared white board, .... At the moment, they are drawbacks with our approach. First, there is no indication about the execution scheme the programmer wants to implement within the configuration language, everything is contained in the implementation of primitive components. This implies that the construction of primitive components must be "autonomous", any process shall be able to access the components through its interface - provided the protection rights are correctly set -. The second drawbacks concerns performance of the runtime. We have deliberately chosen a runtime structure where every OLAN object are present at runtime; as this solution brings flexibility for configuration purpose, it obviously induces performance overhead that we are in the process of measuring. Current Status
The contributions of OLAN consist in supplying:
components, units of that encapsulates other components or ’real’ piece of software; connectors, units that mediate communication. They can be seen as frame whose instantiation produces an interaction. Connectors define what kind of components may be interconnected and what communication protocols they use;
9
interactions, various kind of communication between components. They are decoupled from the implementation and may evolve dynamically according to connectors specification and associative naming; management aspects, that adapt the requirements of the application regarding system resources usage. Future work Future work focuses on the following aspects:
Formalism for the specification of connectors Definition of the specification of management instrumentation and policies Implementation of the overall OLAN framework, which includes the compiler, the runtime support and an environment for 3-D visual programming[14]. Acknowledgment This work is currently part of the SIRAC project. It is partially supported by the European ESPRIT project Broadcast BRA. We would like to thank the SIRAC team and especially Roland Balter, Emmanuel Lenormand, Vlad Marangozov and Jean-Yves Vion-Dury, as well as Andre´ Freyssinet and Serge Lacourte from Bull Research Center / Open Software System.
References [1] Balter R., Ben Atallah S., Kanawati R., “Architecture for Synchronous Groupware Application Development”, Proceedings of the Sixth International Conference on Human-Computer Interactions (HCI International ’95), pp. 371-379, Elesevier, Tokyo Japan, 9-14 July 1995. [2] Barbacci M., Weinstock C., Doubleday D., Gardner M., Lichota R., “Durra: a Structure Description Language for Developing Distributed Applications”, IEEE Software Engineering Journal, vol. Vol.8 , num. No.2 , pp. 83-94, March 1993. [3] Bellissard L., Controle et Configuration pour Appplications Re´parties, Rapport de DEA d’Informatique, Institut National Polytechnique de Grenoble, June 1993. [4] Bellissard L., Ben Atallah S., Kerbrat A., Riveill M., “Component-based Programming and Application Management with OLAN”, in Proceedings of Workshop on Object-Based Parallel and Distributed Computation, LNCS Springer Verlag, Tokyo Japan, June 21-23 1995. [5] Boyer F., “Coordinating Software Development Tools with Indra”, 7th Conference on Software Engineering Environments (SEE’95), pp. 1-13, IEEE Computer Society Press, Noordwijkerhout (Netherlands), 5-7 April 1995. [6] Bull Open Software System, “OODE: Une plate-forme Objet pour les Applications Coope´ratives”, AFCET, AFCET, ed., Paris - France, Novembre 1994. [7] Cutkosky M.R., Engelmore R.S., Fikes R.E., Genesereth M.R., Gruber T.R., Mark W.S., Tenenbaum J.M., Weber J.C., “PACT: An Experiment in Integrating Concurrent Engineering Systems”, Computer Journal, pp. 28-37, January 1993. [8] Kramer J., Magee J., Sloman M., “Constructing Distributed Systems in Conic”, IEEE Transactions, vol. Vol.15 , num. No.6, pp. 663-675, 1989.
10
[9] Magee J., Dulay N., Kramer J., “A Constructive Development Environment for Parallel and Distributed Programs”, Proceedings of the International Workshop on Configurable Distributed Systems (IWCDS), Pittsburgh, March 1994. [10] Marzullo K., Cooper R., Wood M. D., Birman K. P., “Tools for Distributed Application Management”, IEEE Computer, vol. Vol.24 , num. No.8, pp. 42-51, August 1991. [11] Purtilo J.M., “The POLYLITH Software Bus”, ACM TOPLAS, vol. Vol.16 , num. No.1, pp. 151-174, Jan. 1994. [12] Sloman M., Chapter 12 of Network and Distributed Management, vol. ed. by M. Sloman , AddisonWesley, pp 303-347, 1994. [13] Sloman M., Policy Driven Management for Distributed System, num. DoC 93/48, Imperial College Department of Computing, 180 Queen’s Gate, London SW7 2BZ UK, June 1994. [14] Vion-Dury J.-Y., Santana M., “Virtual Images: Interactive visualisation of Distributed Object-Oriented Systems”, Proc. of the Ninth Annual Conference on Object-Oriented Programming Systems, Languages and Applications (OOPSLA), Portland, Oregon, October 1994.
11
Contents 1
Introduction
2
OLAN Component-based language 2.1 Component : : : : : : : : : : : 2.1.1 Interface : : : : : : : : 2.1.2 Implementation : : : : 2.2 Connector : : : : : : : : : : : 2.3 Dynamic evolution : : : : : : : 2.4 Management : : : : : : : : : :
3
1
: : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
Experiments and Results
2 2 2 3 4 5 6 9
12