Component Change and Version Identification in ... - Semantic Scholar

7 downloads 0 Views 154KB Size Report
Relating component and total versioning, the Ragnarok paper [11] mentions the need to reflect component changes in the architecture version identification.
Component Change and Version Identification in SOFA ? Pˇremysl Brada Department of Computer Science and Engineering University of West Bohemia Univerzitni 22, 30614 Plzen, Czech Republic [email protected] http://www-kiv.zcu.cz/

??

Abstract. In the area of component software, the work so far has concentrated primarily on the key issues of architecture specification and component updating. However, the problems of maintaining application consistency and versioning of components as they evolve have received less attention, and the available solutions are either ad-hoc or not well suited for component applications. In this paper we evaluate these solutions and present a new approach to component versioning developed for the SOFA architecture. Based on the analysis of changes between two versions, component revision numbers and change indications are derived as a lightweight compatibility description which is subsequently used for consistency verification during application composition or component update. Thus it is shown how giving the revision numbers a precise semantics and providing additional versioning information provides a support for the tasks of configuration management in component applications.

This paper will appear in the proceedings of SOFSEM’99 conference held on Nov. 27 - Dec. 4, 1999, in Milovy, Czech Republic.

1

Introduction

In the last few years, research as well as practical applications of software component technology became a rapidly growing field. Research in the area is abundant [1, 5, 4, 2] and several commercial systems are available or emerging [7, 9, 8]. While the important architectural issues such as component description languages, connectors and even composition of component-based applications are extensively researched [4, 2, 11], software configuration management (SCM) issues related to component technology have received less attention. ?

??

This work was partially supported by the Grant Agency of the Czech Republic — project 201/99/0244. The author is also with the Department of Software Engineering, Charles University, Prague, Czech Republic; http://nenya.ms.mff.cuni.cz/

As in ‘ordinary’ software systems, the role of SCM in the component world is to help identifying and creating consistent configurations. In this paper we take the view that because revision numbers are used to denote the steps of a software component evolution they implicitly express its backward compatibility and could thus help in consistency checks when a component is being upgraded within an application. The problem is that mostly there are no precise rules for the creation and interpretation of revision numbers. While this is tolerable as long as they are only used and interpreted by humans, it is insufficient for component-based applications where the application should ideally be composed by the user (not the developer) with the help of automated tools. Note: As the term “component” is used to denote many different things in software engineering and research [1], for the purpose of this paper it is defined as black box re-usable piece of software distributed and used in binary form, with defined interfaces (provided and required) and optionally behaviour (semantics). Applications are composed from components using hierarchical aggregation, connectors, or a combination of both.

This paper describes the system for component version and compatibility identification in the SOFA/DCUP (SOFtware Appliances, Dynamic Component UPdating) framework [5], where it is used in component installation and subsequent updates. The rest of this section briefly introduces SOFA principles and architecture. Section 2 describes how the version and compatibility identification is derived, expressed and used in SOFA. A discussion of related work including the approaches to checking compatibility and consistency is in Section 3. The paper ends with remarks on future research directions and a conclusion. 1.1

Overview of SOFA

Software components in SOFA/DCUP [5] are black/grey-box objects with defined interfaces and behaviour. An interface is a named set of method signatures to which a behaviour description (a protocol [6]) is attached. Using regularlike expressions, it describes the allowed sequencing of interface method calls. The black-box view of a component is called component frame and defines the set of interfaces the component will provide to its clients and require from its environment, plus its behaviour protocol (see Figure 1 below). A component’s architecture creates the gray-box view by defining, on the first level of frame nesting, which subcomponents will constitute its implementation. An application is formed by hierarchical nesting of components. Interface and component frame specifications are written in the SOFA Component Description Language (CDL), similarly to other systems [3, 16, 8]. The CDL descriptions of provided interfaces P , required interfaces R, and behavioural protocol B are called specification levels in this paper (the same notation is used for interfaces, where P denotes the method signatures and R is omitted). SOFAnet, the infrastructure which supports component development and deployment, consists of a network of co-operating nodes. Each SOFAnode contains a central template repository (TR) which stores component frames plus

implementations (e.g. in the form of Java package files) as well as their versioning information. Other parts of the node provide various support operations: the Run part is used for launching and running component applications and includes the DCUP interface for run-time updates, and the Made part creates an environment for developing new components.

interface IDBServer { void insert(in int key, in tdata data); void delete(in int key); void query(in tdata mask, out tdata data); protocol: ( insert + delete + query )* // ’+’ means ’either-or’ }; // ’*’ denotes repetition ... frame Database { provides: IDBServer dbSrv; requires: IPlainLogging dbLog; protocol: !dbLog.init ; // outgoing call delegated to the dbLog interface ( ?dbSrv.insert { !dbLog.log } + // an incoming call via dbSrv ?dbSrv.delete { !dbLog.log } + // leads to an outgoing on dbLog ?dbSrv.query )* }

Figure 1: SOFA interface and component frame CDL specification. Versioning in SOFA is based on intensional versioning [12] and implemented via specialised versioning objects stored in the TR. These objects hold both the revision and variant information, one object per each version of a component.

2

SOFA Component Compatibility and Versioning

Despite various attempts described in Section 3, there is no standardised way to classify changes to software units which would support analyses of their compatibility. Such analyses are however necessary for the automation of (component) updates that preserve configuration consistency. In this section, we describe a system developed for the SOFA framework in an attempt to grasp the compatibility and versioning problems clearly and find a working solution. The general definition of component compatibility used here is as follows: for a component C, its version V2 is backward compatible with a previous version V1 if and only if (1) all clients of V1 can use V2 without adaptation and (2) V2 can function in all execution environments of V1 without adaptation. This notion of compatibility takes into account the dependencies of the component in its operating environment, an aspect neglected in some systems [16, 15].

To form a ground for the versioning system we first develop a classification of changes between two revisions of a component based on analysing the differences in their CDL specification levels. Let L1 , L2 ∈ {P, B, R} denote the same specification level in two frame revisions (e.g. the sets of provided interfaces, or the frame protocols). Let F (Li ) be the set of all component frames which can be denoted by Li . When comparing L1 and L2 , we say that – – – –

L2 exactly matches L1 (denoted L2 = L1 ) iff F (L1 ) = F (L2 ) ; L2 is a specialisation of L1 (denoted L2 ⊃ L1 ) iff F (L2 ) ⊂ F (L1 ) ; L2 is a generalisation of L1 (denoted L2 ⊂ L1 ) iff F (L2 ) ⊃ F (L1 ) ; L2 is a mutation of (incomparable to) L1 (denoted L2 4L1 ) iff F (L2 ) 6⊃ F (L1 ) ∧ F (L2 ) 6⊆ F (L1 ) .

This definition of ⊂ on P, B, and R corresponds to the usual understanding (the specialised version has more features and denotes fewer objects) and moreover unifies the comparison of different types of specifications. Thus we can use the same classification of changes for other types of specifications as well (e.g. current interfaces functionality or future component dynamics descriptions). In practice the comparison is based directly on the CDL specification — for provisions and requirements as a set operation on the union of interface method signatures, for protocols as a language inclusion operation. 2.1

Determining Component Compatibility

Based on the specification changes, we classify component1 compatibility as follows (P1 and P2 denote the provided interfaces of two revisions V1 and V2 of one component, similarly Ri and Bi ). V2 is with respect to V1 : – equal, iff P2 = P1 ∧ R2 = R1 ∧ B2 = B1 ; – (strongly) compatible, iff P2 ⊇ P1 ∧ B2 ⊆ B1 ∧ R2 ⊆ R1 ; – conditionally compatible, iff P2 ⊇ P1 ∧ ((R2 ⊇ R1 ∨ R2 4R1 ) ∨ (B2 ⊇ B1 ∨ B2 4B1 )) ; – incompatible, iff P2 ⊂ P1 ∨ P2 4P1 . The strongly compatible version V2 is a straightforward replacement for V1 (variant properties allowing) because it provides more, and has less strict behaviour and requirements (a ‘contravariant’ change). The new revision is incompatible if the provided interface was generalised (reduced) or mutated — an adaptor has to mediate access for clients designed for the old version. The conditionally compatible version has specialised or mutated requirements and/or behaviour (a ‘covariant’ change). From a purely subtyping view, mutation changes on any level constitute subtype incompatibility (e.g. if the Database component from Figure 1 changed its requirements from the IPlainLogging interface to a IUserDefLog interface). However, in practice it is possible that 1

Interface compatibility categories and their defining rules are similar except the R level is missing because interfaces have no dependencies.

the environment in which V2 will be deployed will provide for its requirements (e.g. via a component with the IUserDefLog interface) or behaviour (clients accepting the new protocol). The definitions were therefore relaxed by moving the ‘context-dependent’ incompatibilities into the conditional category. On the other hand, if we allowed to mutate the provided interface for similar reasons the communication with current clients could break, resulting in a loss of functionality. Furthermore, the interface might be eventually changed completely while pretending (by the name) that it is the same type. As both of these effects are clearly undesirable, the SOFA versioning support forces the developer to rename the frame if an incompatible change occurs. 2.2

Revision Numbers and Change Indications

SOFA interface and frame versioning uses the change analysis described above.2 Its results are captured in two complementary data structures: the hierarchical revision number (part of the CDL so that both the developers and the tools can check what has changed), and an indication of the types of changes at each level (stored in component version data as a more specific information for the tools). SOFA revision number is defined for interfaces as an ordered pair (P,B), for component frames as an ordered triple (P,B,R) of natural numbers. A change from the previous revision in a specification level L is homomorfically mapped into an increase of the corresponding part of the revision number. That is, if for example the IDBServer interface is evolved by adding a signature for a method, its revision number part P is incremented (see Figure 2 below). In other words, the revision number’s hierarchical structure is directly derived from the levels of software component specification which in turn have relation to the types of changes. This contrasts with the usual practice of arbitrarily choosing a Major.minor scheme with semantics defined by rules of thumb. interface IDBServer rev 1.1 { void insert(in int key, in tdata data); void delete(in int key); void query(in tdata mask, out tdata data); protocol: ( insert + delete + query )* }; interface IDBServer rev 2.2 { void set(in dbProperties prop); void insert(in int key, in tdata data); void delete(in int key); void query(in tdata mask, out tdata data); protocol: set ; ( insert + delete + query + set )* };

Figure 2: Two consecutive revisions of the IDBServer interface. 2

Technically the analysis is done on the component’s release into SOFAnode’s Template Repository and implemented using comparison of derivation trees.

The change type indication is an ordered pair (p,b) for interfaces resp. an ordered triple (p,b,r) for frames, where p, b, r ∈ {match, gen, spec, mutation }. Its value for two consecutive revisions is computed as described at the beginning of this section. For pairs of non-consecutive revisions it is computed as the maximum value over each pair of intermediate revisions. In the example above, the interface change type indication for revision 2.2 will be (spec, mutation) because the set of interface methods is extended and the new protocol is incomparable to the old one. The compatibility of the whole frame is determined using the definition in Section 2.1, based on the change type values for individual levels. When components are nested, all changes in the nested components are manifested only in the parent component’s architecture. This makes the approach independent on the scale of the composition. 2.3

Examples of Use

Revision and change identification are used in several operations in the SOFA framework. The revision number helps explicitly denote version dependencies — the requires section contains the revisions of interfaces needed for correct operation. Using the compatibility rules, the requirement for IDBServer rev 2.2 in the example below can be satisfied by revision 2.2 but possibly also 2.5 of the interface (because they differ only in the protocol). frame Database rev 2.1.0 { provides: IDBServer rev 2.2 dbSrv; requires: IPlainLogging rev 1.0 dbLog; protocol: // omitted for brevity }

Thanks to the exact meaning of (differences in) revision numbers and change types it is possible to determine, before the new version replaces the current one, if the new configuration can be consistent. For example, suppose an application currently contains revision 1.0.0 of the Database component, revision 2.1.0 is available as an update, and (spec, spec, match) is the corresponding change type indication. The difference between the revision numbers (whose “value” is (1, 1, 0)) indicates that the provisions and behaviour have changed, and from the change type indications we see it was a ‘covariant’ change. SOFAnode determines from this data that the new revision is conditionally compatible with the old one and can replace it only if its frame protocol conforms to that of 1.0.0; thus only the protocol conformance checks will need to be run. Most of this work can be done without analysing the full CDL source (which may be a computationally intensive task) and without the need to shut down the application — this is particularly important for high-availability systems.

3

Related Work

Ensuring that consistent software configuration is composed from its constituent units as well as classifying changes in software units and their impact on compat-

ibility are the subject of several academic research projects as well as commercial systems. However, not always there is an explicit relation to versioning. The work of Perry [13, 14] on software unit compatibility and its impact on architecture consistency is rigorous and clearly put in the SCM context, but no link is made to versioning as such. Also, the consistency checks are always done on full function specification which may be impractical for larger systems. Relating component and total versioning, the Ragnarok paper [11] mentions the need to reflect component changes in the architecture version identification. However, this identification is described without detail and the types of architecture changes are not classified. Research on the C2 system at University of California [4] is concerned with static and run-time modifications to the application architecture. The authors assert that modification constraints need to be verified to ensure configuration consistency but do not provide any details about relevant methods. The versioning approach presented in this paper can thus be seen as one such method suitable for coarse-grained components. In the Java language system [15], compatibility checks are done partly at link- and partly at run-time when inheritance or interface conformance problems are solved by exception handling. The JDK version 1.2 also defines the package version identification as a triple (major, minor, micro) of natural numbers. However the meaning of these numbers lacks a precise definition, namely any relation to the compatible changes defined in the language specification. The DCE (Distributed Computing Environment) [16] defines precisely what server interface changes are (in)compatible and how they are reflected in the interface revision ID. Clients using an interface with an incompatible version number may be refused by the server. This is a well engineered system but the compatibility rules are too rigid, and the fine granularity (interfaces only) and lack of behavioural specification make it insufficient for component versioning.

4

Open Issues and Future Research

The work on SOFA component revisioning so far has resulted in the specification of its principles and algorithms. At the time of writing, a prototype implementation of the system is being developed. Its main functions will be to perform the change analysis and generate the revision numbers and change type indications into the CDL source and SOFA node data structures, and to check compatibility based on the version information and CDL sources. The proposed model has obviously some weaknesses and open issues as well. First, due to the method of computing revision numbers it is not possible to identify branches, i.e. alternative but backward compatible versions of an interface or component frame specification. The proposed solution to this problem is that if a branch is created (because there already exists a subsequent trunk revision) it would be required to have a different name but could specify the name and revision from which it was derived.

Also, the notion of shared dependencies as defined in [14] (in our case, formats of data created by the component etc.) is not considered in the current compatibility definitions. This may lead to run-time problems undetected during the checks preceding component update. Future research in this project will therefore focus on these issues, mainly how to include data format dependencies in the revision and change type indication. Generalisation of the branching problem is also the need to specify compatibility of interfaces and components developed by different providers, as provider identification is part of the name.

5

Conclusion

The novel software component versioning approach presented in this paper creates ‘semantically rich’ software component revision numbers and change identifications based on the analysis of component CDL specification. Using the revision and change type information as a first sentry, and the full component CDL description for complete checks, configuration consistency of the prospective update can be detected automatically without the need to shut down the (possibly running) application. At the same time the ascending sequence of revision numbers conveys the traditional meaning of the historical order of component development. Future work on the system includes solving the open issues of branching and data compatibility, as well as developing a working implementation. In a wider context, a modification of this versioning approach could be used for other systems, e.g. DCE and various Unix package deployment systems.

References 1. Szyperski, C.: Component Software. ACM Press, Addison-Wesley 1998. 2. Allen, R., Garlan, D.: Specifying Dynamism in Software Architectures. Proceedings of Foundations of Component-based Systems Workshop, 1997 3. Magee, J., et al: Specifying Distributed Software Architectures. Proceedings of ESEC’95, Barcelona, Spain. 4. Oreizy, P.: Issues in the Runtime Modification of Software Architectures. TR-96-35. University of Carolina, Irvine, 1996 5. Pl´ aˇsil, F., B´ alek, D., Janeˇcek, R.: SOFA/DCUP: Architecture for Component Trading and Dynamic Updating. Proceedings of ICCDS 98, Annapolis, Maryland, USA. 6. Pl´ aˇsil, F., Viˇsn ˇovsk´ y, S., Beˇsta, M.: Behavior Protocols and Components. Proceedings of TOOLS USA ’99, Santa Barbara, CA, August 1999. 7. JavaSoft: JavaBeans 1.0 Specification. http://www.javasoft.com/beans/spec.html 8. CORBA Components, Joint Revised Submisstion. OMG orbos/99-02-05 9. Rogerson, D.: Inside COM. Microsoft Press 1997 10. IEEE Standard 1042-1987: Guide to Software Configuration Management. IEEE 1994 11. Christensen, H.B.: Experiences with Architectural Software Configuration Management in Ragnarok. Proceedings of SCM-8 Workshop, ECOOP 1998. Springer-Verlag 1998.

12. Conradi, R., Westfechtel, B.: Configuring Versioned Software Products. Proceedings of SCM-6 Workshop, ICSE’96, Berlin, Germany. LNCS, Springer-Verlag 1996. 13. Perry, D. E.: Version Control in the Inscape Environment. Proceedings of ICSE’87, Monterey, CA. 14. Perry, D. E.: System Compositions and Shared Dependencies. Proceedings of SCM6 Workshop, ICSE’96, Berlin, Germany. LNCS, Springer-Verlag 1996. 15. JavaSoft: The Java Product Versioning Specification. http://www.javasoft.com/docs/jdk1.2/docs/guide/versioning/ 16. Peterson, M. T.: DCE: A Guide to Developing Portable Applications. McGrawHill, 1995.