Maintaining Shared Workspaces Consistency during ... - CiteSeerX

1 downloads 65481 Views 231KB Size Report
intermediate result of graph produced by A1 allows A2 to start building the application app earlier, before the termination of A1. A2 edits the application app.
Maintaining Shared Workspaces Consistency during Software Development Hala Skaf Group ECOO, LORIA, BP. 239 54506 Vandoeuvre-Les-Nancy Cedex, France,[email protected] Francois Charoy Group ECOO, LORIA,BP. 239 54506 Vandoeuvre-Les-Nancy Cedex, France, [email protected] and Claude Godart Group ECOO, LORIA,BP. 239 54506 Vandoeuvre-Les-Nancy Cedex, France, [email protected] The development of large software is always done by teams of people working together and struggling to produce quality software within their budget. Each person in these teams generally knows his job and wants to do it, without being bothered by other people. However, when people work towards a common goal they have to exchange data and create dependencies between each other regarding these data. If these people have to follow a process, cooperating and synchronizing with co-workers and trying to reach one's own goal becomes too dicult to manage. This may leads to frustration, lower productivityand reluctancy to follow the prede ned process. This is why some support is needed to avoid common mistakes that occur when people exchange data. In this paper, a hybrid approach to support cooperation is presented. The originality of this approach is the ability to enforce general properties on cooperative interactions while using the semantic of applications to t particular situations or requirements. This paper gives a brief idea about the general enforced properties on activity interactions. It describes in detail the semantic rules that control activity results, the impacts of the cooperation on these rules and how both of dimensions interact.

Keywords : Cooperation, Cooperative Environment, Constraints, Consistency.

1. Introduction The development of large software is always done by teams of people working together. Most of the time, these people are struggling to produce quality software within their budget. Each person in these teams generally knows his 1

job and wants to do it in the best conditions, without being bothered by other people. However, when people work towards a common goal, it is very common that they have to exchange data and that they create dependencies between each other regarding these data. If their common organization tries to impose a process to them, it may happen that, following this process, cooperating and synchronizing with co-workers and trying to reach one's own goal becomes too dicult for them to manage. This may lead to frustration, lower productivity and reluctancy to follow the prede ned process. This is why some support is needed to help people in one of the less interesting part of their jobs: be sure that the process will look like it has been followed and avoid common mistakes that occur when people exchange data. In this paper, we will consider people who cooperate in a shared workspace in order to reach their goal. This goal is a sub-goal of the team common goal. We suppose that these people are willing to cooperate and to produce the best result they can. We also suppose that they agree to follow some prede ned process but that they don't want to lose precious time due to this process. In this context, two approaches are usually proposed to support cooperation among people: encapsulate their activities in transactions to enforce general properties on activity interactions, or describe the cooperation process with semantic rules as part of the general development process. The transactional approach is based on advanced transaction models that allow more concurrency between activities[1]. The transactional point of view considers each person's activity as a transaction that has to be completed to reach the sub-goal. The process point of view [2, 3, 4] considers each person's activity as a task which has to be completed in a prede ned order and with some speci c conditions. Most of the time, approaches that cover these two points of view are biased towards one of them. However, these two points of view are essential in cooperative applications because there is no single correctness criterion like those proposed by the transactional approach to support cooperation. Rather, the notion of what is correct may vary from application to application and from task to task. Hence we need semantic rules. But unfortunately semantic rules do not allow to enforce general properties on activity interactions. In this paper, we address this limitation by proposing a hybrid approach to support cooperation. This approach enforces general properties on activity interactions and uses the semantic of applications to t particular situations or requirements. This paper gives a brief idea about the general enforced properties on activity interactions, describes in detail the semantic rules that control activity results and how both of dimensions interact. The rest of the paper is organized as follows: The next section provides an overview of the context in which we are placing this work and gives the main principles of the hybrid approach. Section 3 shows how the correctness 2

of activities results is speci ed by means of constraints de ned on states and state sequences of the shared workspace. Section 4 illustrates the impacts of cooperation on constraints and the impacts of constraints on cooperation. It de nes a new algorithm for monitoring constraints in cooperative applications and provides three strategies to evaluate them in this context. Section 5 gives a brief idea about the implementation done in the COO software development environment. Section 6 concludes the paper.

2. Cooperation and Software Development

Cooperation can be considered from many points of view [5]. In this paper, we consider cooperation from the point of view of working and exchanging data asynchronously in a shared and persistent workspace. This corresponds to something very common in software development environment. Development objects (speci cation, code .. .) are stored in a repository (a database, a con guration management system or a le system). Users associated to the development activities access these objects to modify them.

Repository

Development activities

Specify(graph)

Build(graph)

Build(graph,app)

Users

Fig. 1.

Development Environment

Each development activity has its own goal which may be divided in subgoals. For example, in gure 1, the goal of the activity Build(graph) is to build the library graph. In order to achieve their goal, activities cooperate.

2.1. Cooperation Principles

In our context, we consider only speci c kind of cooperation. We say that two activities cooperate if they exchange results during their execution through a shared workspace. We distinguish between two kinds of results: intermediate 3

results and nal results.

Intermediate Results are preliminary results produced by activities during their execution.

Final Results are development objects produced by activities at their termination.

To illustrate this, let us consider the activities A1 : Build(graph) and A2: Build(graph,app). A1 builds a graphical library graph and A2 uses this library to build an application app. The gure 2 shows the history of the activities A1 , A2 and the di erent states of the repository. A state of a repository is a collection of the values of all objects in the repository at a given time. A1 : Build(graph) begin(A1 ) spec1 read(spec) graph1 = edit() write(graph; graph1 ) graph1 = edit(graph1 )

repository (spec; v0 )

A2 : Build(graph; app) begin(A2 )

(graph; v1) (spec; v0 )

end

(graph; v2 )(spec; v0 ) (graph; v2)(app; v3)(spec; v0 )

Fig. 2.

graph2 read(graph) app2 = edit() graph2 end

read(graph)

Cooperative Execution

An object in the repository is de ned by a couple (id; v) where id is the object identi er and v is its value. The above execution can be interpreted as follows:

 At the beginning of A1 , the repository contains only the object spec with

v0 as value. We represent the initial state of the repository by: (spec, v0) .  The user working in A1 starts building the context of his activity. He accesses the speci cation of the library spec, then creates a local copy spec1 of that object in the local memory of his activity (spec1 read(spec)).  He invokes a tool to create a local object graph1 (graph1 = edit()).  Then he publishes a result of graph. This result is intermediate since it is produced during the execution of A1 . We represent the intermediate result of the object graph by: (graph, v1) . When A1 produces the intermediate 4

result of graph, it produces at the same time a new state of the repository. This is an intermediate state. We represent it by: (graph, v1) (spec, v0) . Each time A1 publishes an intermediate result, it also produces a new intermediate state of the repository. The user of A1 repeats the previous steps until the end of his activity.  At its termination, A1 produces the nal result of graph and a new state of the repository. This state is represented by: (graph,v3)(spec,v0 ) . The nal value of graph in this state is persistent in the repository. The only way of modifying this value is to restart a new activity.  In the same way, the user of the activity A2 builds the working context of his activity by reading the intermediate result of graph. Notice that the intermediate result of graph produced by A1 allows A2 to start building the application app earlier, before the termination of A1 .  A2 edits the application app. It reads again graph and modi es the application. Finally, it produces the nal result of app and terminates its execution. This execution is a simple example of a cooperation between two activities. It shows how cooperation can be useful and harmful at the same time. In this case, the user of A2 can start his work early with a preliminary version of graph. This is good for productivity. Users do not have to lose their time waiting for some result to start their work. This can also be harmful if A2 does not take care to update his work with the nal version of graph. This may cause some major inconsistencies that would not exist without cooperation. Our proposal tries to overcome these problems while providing users with more exibility. We want users to keep the control, i.e., how, when and with whom they cooperate, and to help them to avoid possible inconsistencies that may be induced by the cooperation. To reach this goal, we propose an approach that takes into account at the same time the correction of interaction between activities and the correction of activity results in order to ensure what we will call hybrid correctness.

2.2. Hybrid Correctness Principle

Our approach to support useful cooperation while avoiding its dark side is to separate correctness into two dimensions: correctness of cooperative interactions and correctness of individual behavior [6].

Correctness of cooperative interactions tackles the problem of concurrency control. In other words, it synchronizes the exchange of shared objects between activities. This correctness dimension is ensured by a syntactic protocol described in section 2.3. Correctness of individual behavior avoids semantic errors introduced by the users associated to an activity. It takes into account the values of the 5

products (is the product tested, is the code compiled without errors ?) and the sequences of values of products (the product is tested before its delivery to the client ..). This dimension is ensured by a constraint monitoring algorithm that we detail in section 3. We want to be sure that both dimensions are taken into account during development activities, i.e. that neither cooperative interactions nor individual behaviors introduce inconsistencies. We want to be sure that all executions that are accepted by our system belong to the intersection between activities that have consistent results and those that have correct interactions (Fig. 3).

tions

Con sis

tent

Re

su

lts

Execu tions Set

ac Inter Correct

Fig. 3.

Executions sets

One of the main issue in this context is that we cannot consider activities and their executions one by one but as a whole. Interactions due to cooperation introduce dependencies that have to be managed. Another fundamental issue is that users are behind activities. They are working interactively and are conducting creative actions. They do not want to be bothered by other users actions and they do not want to see their work corrupted by others. Users need to keep control on the way they cooperate. Our general philosophy regarding both dimensions is to allow users to do almost anything that they want, provided that, at the end of their activities, from an external point of view, everything appears just as if things had been done following the right process and without inconsistencies. Both dimensions that are described in the following sections have been de ned with this idea in mind.

2.3. Correctness of Cooperative Interactions

To overcome synchronization problems between activities which are executed in parallel, we use a transactional approach: each activity is executed as a 6

cooperative transaction (COO-transaction) [7]. The main di erence between COO-transactions and classical transactions (ACID transactions) [8] is that COO-transactions are not isolated.Two COOtransactions can cooperate by exchanging data during execution through the repository. Of course, the others properties Atomicity, Consistency and Durability [9] are preserved. The COO-transaction model proposes a syntactical correctness criterion: the COO-serializability [7]. This criterion can be seen as an evolution of the classical correctness criterion of transactions, serializability [9] to support cooperative execution. The COO-serializability criterion guarantees that during cooperative interactions, dirty read will be compensated and that there will be no lost update (all nal results will be taken into account) [7]. These properties of cooperative interactions are enforced by a syntactical protocol (COO-protocol) which synchronizes the exchange of results among cooperative transactions. It is based on the following synchronization rules: 1. If a transaction produces an intermediate result then it must produce the corresponding nal result at the commit time. 2. If a transaction reads an intermediate result of another transaction then it must read the corresponding nal result. 3. If a transaction reads an intermediate result of another transaction then it becomes dependent on that transaction. This dependency is deleted when the transaction reads the corresponding nal result. 4. In the case of a cyclic dependency among transactions, the transactions are grouped. They form a group of cooperative transactions. All transactions in a group must terminate their execution at the same time and in an atomic way (all or nothing). The execution of the gure 2 is COO-serializable: A2 has read the nal result of graph produced by the transaction A1 . This means that the cooperative interaction of A1 and A2 is correct. Imagine now that transaction A2 does not read the nal result of graph (Fig. 4). The execution of the gure 4 is not COO-serializable: the user of A2 has read an intermediate result of graph but he has not read the corresponding nal result. In this case, the dirty read of the object graph has not been compensated. The transaction A2 can not terminate its execution. The termination operation of A2 is canceled and A2 remains active. The COO-protocol based on COOserializability never oblige a transaction to abort its work. To summarize, the COO-protocol has the following advantages. It leaves to the users all the initiative regarding cooperation. A user may publish an intermediate result at any time. A user may or may not read intermediate results published by other users. If he does so, he will have to pay some price at the end to resynchronize himself with the nal version of the result he read. From the outside, things will look like he did his work from this last version, 7

A1 : Build(graph) begin(A1 ) spec1 read(spec) graph1 = edit() write(graph; graph1 ) graph1 = edit(graph1 ) end

repository (spec; v0 ) (graph; v1) (spec; v0 ) (graph; v2 )(spec; v0 ) (graph; v2)(app; v3)(spec; v0 )

Fig. 4.

A2 : Build(graph; app) begin(A2 )

graph2 read(graph) app2 = edit() end

Incorrect Cooperative Interaction

without having to wait until the end of the activity on which he did depend. In this context, we say that activities are not isolated but insulated [10]. The syntactical protocol, introduced above, allows to control the correctness of cooperative interactions, but it does not avoid errors due to inconsistent behaviors of activities users. Let us consider the execution of the gure 2. The cooperative interaction of this execution is correct according to the COO-serializability: the transaction A2 has read the nal result of graph. However, we do not have any guarantee on the quality of graph (is graph tested ?, compiled without errors ? ) nor about how graph has been produced (is graph compiled before it has been tested .. .). The goal of the individual correctness is to provide such a guarantee without restricting the ability for users to cooperate.

3. Correction of Activity Results

A common way to provide guarantees on product quality is to de ne a set of constraints in the repository and to check that these constraints are veri ed. It is widely recognized that the quality of a product is not only a ected by its properties but also by its production process. In our context, where activities do not produce simple database update but actual products, constraints should not only guarantee properties on states but also on the way these states are produced. To support that, we need to express constraints that cover both dimensions Static constraints describe the properties of objects that must hold in each state of the repository. These constraints represent, in some way, quality criteria of a product. For example, \the design of a module is approved". Intuitively, this constraint describes the fact that at each moment the design of each module, which is accessible in the repository, is approved. 8

Static constraints do not allow to de ne constraints on process i.e. constraints on states transition and on state sequences. For instance, we can not de ne constraints like \the product is never delivered to a customer before its veri cation". This is why we need dynamic constraints. Dynamic constraints de ne properties that must hold on states sequence of the repository. They de ne, in some way, criteria on the quality of processes. For example, \the code of a module is never produced before the validation of its design", means that it is necessary to have in the repository a state in which the design of a module is approved before having a state in which the code of that module is developed.

3.1. Constraints De nition

Our model to de ne constraints is based on the work of [11, 12]. Each constraint is de ned as follows: ci (x1 : t1 ; : : :; xn : tn) : (x1; : : :; xn) where ci is the constraint identi er, x1 ; : : :; xn are free variables, t1; : : :; tn are types respectively of x1; : : :; xn (our objects are typed, each object has a type. For example, d: Design means that the object d is of type Design).  is the formula to verify. A formula is built from non temporal formula ( rst order predicate, by iterative applying of logical connectives: ^; _; ); :) extended with temporal operators (always, sometime, after, before . .. ) [13]. For example, the static constraint \The design of a module is approved" can be de ned by: c1 (d : Design) : always approved(d) approved is a predicate. It is true if the variable d is approved and false otherwise. The dynamic constraint \A product delivered to a client has been tested before" can be de ned by: c2(prod : Product) : sometime approved(prod) before delivered(prod) approved (delivered) is a predicate. It is true if the product is approved (delivered) and false otherwise. Temporal logic has been used in our environment because it provides us with a unique formalism to describe both static and dynamic constraints declaratively [14]. However, the approach we propose in the following sections could be applied with other formalisms (Petri nets, for example).

3.2. Monitoring Constraints in a Cooperative Environment

The fundamental hypothesis on which are based all constraints monitoring algorithm is that transactions are serializable and atomic [15]. Everything appears just like if the transactions were executed one after the other. Thus algorithms 9

do not have to consider any kind of interaction between them. Moreover, transactions can be rolled back and in the case of constraints violation, the transaction is aborted. These hypothesis cannot be applied in our case. Transactions are neither isolated nor serializable and they are of long duration. We cannot force them to abort. Moreover, we cannot consider that each state of the repository will be consistent regarding constraints. Our approach does not only break isolation but it also breaks consistency. 3.2.1. Basic Principles A new state is produced each time a result, nal or intermediate, is produced. However, constraints cannot be checked with intermediate values. Constraints checking on intermediate values would reduce greatly the ability of users to cooperate as they would be obliged to publish only consistent values. Just as intermediate values can be published without considering serializability, they may also be published without considering consistency. This means that as in the case of classical transactions, intermediate results produced during the transaction execution, are not controlled by constraints. In fact, monitoring the consistency of intermediate results would reduce their usefulness [16]. Proceeding in this way allows to con rm that the constraints do not reduce the

exibility of the environment: in spite of the presence of the constraints, the user of a cooperative transaction can work as \he wishes" and especially he can cooperate (exchange intermediate results) without actually taking care of the process. 3.2.2. Impact of cooperation The main impact of cooperation on constraints evaluation is related to the fact that activities do not execute in isolation and can share intermediate results. As a consequence, if, as traditionally, constraints are checked on the new state produced at the end of the activities, all the constraints cannot be checked. Let us take two activities t1 and t2. t1 : Modify(dA), t1 modi es the design of module A and t2 : Modify(cA) modi es its code. Suppose also that we have the following constraints:

 c1: The designs of the modules are approved, which is de ned by: \c1(d : Design) : always approved(d)", approved is a predicate which is true

if the variable d is approved and false otherwise. Only the transactions which manipulate objects of type \Design" can instantiate this constraint.  c2 The code of all the modules is compiled which is de ned by: \c2(c : Code) : always compiled(c)", compiled is a predicate which is true if the variable c is correctly compiled and false otherwise. Only the transactions which manipulate objects of type \Code" can instantiate that constraint. 10

These constraints are de ned in the repository. Figure 5 shows a possible execution of t1 and t2 .

t1 : Modify(dA) begin(t1 ) dA1 read(dA) dA1 = edit(dA1) write(dA; dA1)

repository c1 (d : Design) : always approved(d) c2(c : Code) : always compiled(c) (dA; approved)(cA; compiled) (dA; v0) (cA; compiled) (dA; v0) (cA; v1)

dA1 = edit(dA1) dA1 = approve(dA1 ) end

begin(t2 ) cA2

read(cA)

dA2 read(dA) cA2 = edit(cA2 ) write(cA; cA2)

(dA; approved) (cA; v1 ) (dA; approved)(cA; compiled)

Fig. 5.

t2 : Modify(cA)

dA2 read(dA) cA2:obj = compile(cA2 ) end

Cooperative execution of t1 and t2 in the presence of the constraints c1 and c2 .

 t1 modi es the design of the module A (dA), then it produces an intermediate result of dA.

 t2 reads this intermediate value, modi es the code and produces an intermediate result of the code.

 After some modi cations of the design, t1 tries to terminate its execution.

t1 can terminate its execution: the Coo-protocol is veri ed (t1 does not read an intermediate result of t2 ) and the constraint c1 is veri ed (the nal result of t1 (the design of module A dA) is approved).  The state of the repository produced at the termination of t1 is consistent with respect to the constraint c1 . We symbolize such a a state by: (dA; approved) (cA; :compiled) . In this state, dA veri es the constraint c1 . However, the constraint c2 is not considered, as the result of t1 has no impact on it. Thus although there is an intermediate result in the repository that prevents constraints checking, we may accept t1 termination. We suppose that in some future state, t2 will produce the valid nal result that will satisfy all the constraints.  At the end of t1 , the object dA is consistent and at the end of t2 , the object cA is consistent. Thus, at the end of t1 and t2 all the objects in the repository are consistent i.e. the repository is in a consistent state. 11

Formally, the degree of consistency ensured by cooperative transactions is weaker than the one ensured by classical transactions: we can not say that the repository is in a consistent state at the end of each transaction. However, we consider that it is sucient in a cooperative framework because it allows to ensure users that they are working in a correct way and that a consistent state will be reached in the future. In other words, in cooperative framework, only objects modi ed by transactions must be consistent. In contrast, it is important to ensure that all the objects will be consistent at the end of all cooperative transactions. In the COO environment, this is ensured on the one hand, by the syntactical protocol (Section 2.3) and on the other hand, by the constraints monitoring algorithm which ensures the consistency of nal results. One of the main issues that remains is that sometimes a transaction cannot terminate because some intermediate values prevent the evaluation of the constraints that are concerned by the transaction results. These intermediate values may have been produced by another transaction. As we said before, our general philosophy implies that users do not want to be bothered by cooperation. However, they have sometime to pay some price for that. This is what is explained in the following section.

4. Constraints Evaluation with Intermediate Results

A constraint is evaluable if all the objects that can instantiate this constraint are nal results, i.e. are not intermediate results. For example, if we consider the constraint \c1(x; y): always (x < y)" which means that the value of x is always smaller than the value of y. The initial value of x is 100, the initial value of y is 150, the transaction t1 modi es the object x and the transaction t2 modi es the object y, as shown in the gure 6.

t1 x1

begin(t1 ) read(x)

x1 = x1 + 50 write(x; x1) x1 = x + 20 end ! annulate

Fig. 6.

repository c1 (x; y) : always (x < y) (x; 100)(y; 150)

(x; 150) (y; 150) (x; 150) (y; 120)

t2 begin(t2 ) y2 read(y) y2 = y2 ? 30 write(y; y2)

The constraint c1 is not evaluable at the end of t1 .

12

 The transaction t1 modi es the object x and publishes an intermediate

result of x.  The transaction t2 modi es the object y and publishes an intermediate result of y.  At the termination of t1 , constraints are checked. c1 is not evaluable because of the object y which can instantiate c1 and it is an intermediate result of t2 . In this situation the constraint c1 is not evaluable. The termination operation of t1 is aborted. To overcome this kind of problem, we have studied the three following strategies: 1. The transaction terminates its execution and delegates the validation of its constraints to other active transactions. 2. It evaluates its constraints on the last nal results of the objects, which are not nal. 3. It delays its termination until it can evaluate its constraints, i.e., new nal values are produced. In the following, we detail these di erent strategies and explain the advantages and the disadvantages of each one.

4.1. First strategy: The Other Will Validate the Constraints

According to this strategy, the transaction t1 of the gure 6 can terminate its execution. t1 supposes that t2 will validate c1 at its termination. Thus, we can have the state: (x,170) (y, 120) at the end of t1 (Fig. 7).

t1 x1

begin(t1 ) read(x)

x1 = x1 + 50 write(x; x1) x1 = x1 + 20 end

Fig. 7.

t1

repository c1 (x; y) : always (x < y) (x; 100)(y; 150)

(x; 150) (y; 150) (x; 150) (y; 120)

t2 begin(t2 ) y2 read(y) y2 = y2 ? 30 write(y; y2)

(x; 170) (y; 120)

terminates its execution without validating the constraint c1

This solution can lead to di erent kind of problems: 13

1. If t2 wants to abort, the repository becomes inconsistent. 2. t2 may also do the same with other transactions (with other constraints) and at the end none will be able to produce a consistent state. This solution removes the responsibility of activity to produce consistent results. This is incompatible with our vision of cooperation.

4.2. Second strategy: Constraints are Validated Against the Last Consistent Results

Another possible solution is to evaluate constraints on the last nal consistent results. The execution in the gure 8 illustrates this strategy.

t1 x1

begin(t1 ) read(x)

x1 = x1 + 50 write(x; x1) x1 = x1 + 20 end ! annulate x1 = x1 ? 30 end

Fig. 8.

repository c1 (x; y) : always (x < y) (x; 100)(y; 150)

(x; 150) (y; 150) (x; 150) (y; 120)

t2 begin(t2 ) y2 read(y) y2 = y2 ? 30 write(y; y2 )

(x; 140) (y; 120)

At its termination t1 evaluates the constraint c1 on the last consistent value of y.

 At the end of t1, its constraint c1 is not evaluable because of the intermediate result of y produced by t2.

 t1 can evaluate c1 on the last nal consistent value of y. In the above

execution, the last nal consistent value of y is (y = 150).  Now the transaction t1 can terminate its execution: the constraint c1 is valid for (x = 140; y = 150).

Note that, in some cases, the constraint may be evaluated to false. In this case, the user of the transaction has to continue working until the satisfaction of the constraint. This is a valid solution when at least two versions of each object are kept. It has the advantage of avoiding t1 to be bothered by t2 when t1 does not want to 14

cooperate with t2 . In this case, t1 is actually serialized before t2 as in a classical case without cooperation. This strategy has two main disadvantages. On the one hand, it compares objects of di erent generations. In some cases this does not have sense. For example, it is not really interesting to compare the speci cation and a code of the same module but of two di erent generations (versions). On the other hand, it is necessary to store at least the last two values (versions) for each object. The current value and the last consistent one. This means that we need a multi-versions repository (at least two versions) to control the di erent versions of objects. However, it has a main advantage which is avoiding t1 to be bothered by t2 , if it does not want to, i.e. t1 is not obligated to cooperate.

4.3. Third Strategy: Waiting for the new nal results

If at the termination of a transaction, its constraints are not evaluable then its termination operation is aborted and the transaction waits for the termination of other transactions (Fig. 9). repository c1 (x; y) : always (x < y) (x; 100)(y; 150)

t1 begin(t1 ) x1 read(x) x1 = x1 ? 20

begin(t2 ) y2 read(y) y2 = y2 ? 30

end ! wait end

Fig. 9.

t2

(x; 100) (y; 120)

write(y; y2 )

(x; 100)(y; 120)

end

(x; 80)(y; 120)

t1

is waiting for the termination of t2

 At the end of t1, the constraint c1 is not evaluable because of the intermediate result of y produced by t2 . t1 waits for the termination of t2.  After the termination of t2 , the constraint c1 becomes evaluable. t1 checks c1 and terminates its execution.

This strategy can introduce in some cases a \deadlock" between the transactions. Suppose now that the transaction t1 has produced an intermediate result of x and t2 has also produce an intermediate result of y (Fig. 10). 15

repository c1 (x; y) : always (x < y) (x; 100)(y; 150)

t1 x1

begin(t1 ) read(x)

x1 = x1 ? 20 write(x; x1)

(x; 80) (y; 150) (x; 80) (y; 120)

end ! wait

Fig. 10.

t2 begin(t2 ) y2 read(y) y2 = y2 ? 30 write(y; y2 ) end ! wait

t1

waits for t2 and t2 waits for t1 .

In this execution, t1 must wait for the termination of t2 and in the same time t2 must wait also for the termination of t1 . In this situation, there is a deadlock between t1 and t2 . In fact, reaching a deadlock between transactions means that each transaction needs the other one. A very rough solution in this case is to apply the rst strategy to remove the deadlock. A better solution to this problem is to invite the transactions to cooperateain order to terminate their execution simultaneously. If we apply this strategy to the previous example, the two transactions t1 , t2 can cooperate by reading their intermediate results reciprocally (Fig. 11).

 t1 reads the intermediate result of y produced by t2 and starts a cooper-

ation with t2 .  Then t2 reads the intermediate result of x produced by t1 and starts a cooperation with t2 .  t1 has read an intermediate result of t2 and t2 has read an intermediate result of t1. These two transactions are grouped by the syntactical protocol of COO (cf. section 2.3). t1 and t2 form a group of cooperative transactions and must terminate their execution at the same time. The termination of a group of cooperative is inspired from two phases commit protocol [8] as we shall see below.

Constraints and Cooperative Transaction Groups

In the case of a cyclic dependency between cooperative transactions, the transactions are grouped by the syntactical protocol and form a group of cooperative aOf

course, starting a cooperation with other users is under the individual responsibility of each user. The environment does not obligate users to cooperate.

16

t1 x1

begin(t1 ) read(x)

x1 = x1 ? 20 write(x; x1)

repository c1 (x; y) : always (x < y) (x; 100)(y; 150)

(x; 80) (y; 150) (x; 150) (y; 80)

y1

Fig. 11.

read(y)

t1

t2 begin(t2 ) y2 read(y) y2 = y2 ? 30 write(y; y2) x2

read(x)

and t2 cooperate to make the constraint c1 evaluable.

transactions [17]. A cyclic dependency appears between two transactions when the rst one reads an intermediate result of the second and reciprocally. Transactions in the same group terminate their execution together in an indivisible way (all the transactions terminate or none) and produce only one state of the repository. With respect to the constraints, a group of cooperative transactions can be seen as a unique transaction. This transaction terminates its execution when the last transaction in the group terminates. The constraints of the group are the union of the constraints of the transactions composing the group. Thus, the termination of the last transaction of the group is the same as a termination of an ordinary transaction: at its termination, the transaction must produce a \consistent state" of the repository. In this state, all the constraints must be evaluable and valid. Consider again the execution of the gure 11. In this execution, the transaction t1 and t2 can terminate their execution as depicted in the gure 12. (Remember that the transaction t1 cooperate with t2 in order to make the constraint c1 evaluable). The execution of the gure 12 is interpreted as follows:

 t1 reads an intermediate result of y produced by t2. t1 becomes dependant y of t2 on the object y: t1 ! t2.  In the same way, t2 reads an intermediate result of x produced by t1. t2 x becomes dependant of t1 on the object x: t2 ! t1 . The transactions t1

and t2 form a group of cooperative transactions.  The transaction t1 starts the termination of the group by trying to terminate. It produces a set of \potentially" nal results and becomes \ready to terminate". 17

t1 x1

begin(t1 ) read(x)

x1 = x1 ? 20 write(x; x1)

repository c1(x; y) : always (x < y) (x; 100)(y; 150)

(x; 80) (y; 150) (x; 80) (y; 120)

y1 read(y) x1 = x1 + 10 end : ready to terminate end

Fig. 12.

t1

t2 begin(t2 ) y2 read(y) y2 = y2 ? 30 write(y; y2 ) x2

read(x)

(x; 90) (y; 120) (x; 90)(y; 120)

x2 read(x) end

and t2 terminate their execution at the same time

 The transaction t2 tries to terminate its execution, its termination oper-

ation is rejected since t2 has not read the \potentially" nal result of x produced by t1. t2 continues its execution. It reads the value of x and accepts to terminate with this value. At the termination of t2 (the last transaction of the group), the constraint c1 of t1 and t2 is evaluable and valid. Thus, t2 can terminate its execution. The termination operation of t2 terminates the execution of t1 and t2 simultaneously.

The above example shows how the cooperation allows the transactions t1 and t2 to satisfy their constraints.

4.4. Summary

In summary, in the case of cooperative activities, the monitoring algorithm can be de ned as:

if the constraint is not evaluable then

apply the second or the third evaluation strategy

else if the constraint is not veri ed then continue working

else

produce a new state (Commit)

endif endif

The second strategy evaluates the constraints on the last nal results of the 18

objects while the third strategy delays the transaction termination and invites it to cooperate with other transactions. To check the validity of the constraints, we have adapted the approach developed in [18, 12] as detailed in [14, 19]. If a constraint is not valid, it is the responsibility of the user to continue working until the satisfaction of the constraint. Notice that in some situations although the user continues working, he is unable to validate the constraints. To solve this problem, we propose in [20] two forward recovery technics but this is out of the scope of this paper.

5. Implementation The syntactical protocol and the constraints monitoring algorithm described in this paper have been implemented in the COO software engineering environment. COO is organized in services [21]. The Transactional Service implements the syntactical protocol. The Constraints Service implements the constraints monitoring algorithm. The constraints are represented by formulae of temporal logic. As we said, we have adapted the approach developed in [18, 12] to check the validation of the constraints as described in [14]. The implementation of the algorithm has been done in the case of a at organization of the activities (all the activities are at the same level and they shared the same database) and in the case of a hierarchical organization (model of nested transactions) [19, 20].

6. Conclusion In this paper, we have shown from a theoretical point of view that it is possible in a software development environment to reconcile the need of freedom of developers and the control mania of managers. The hybrid approach of Coo provides a framework which allows people to exchange informations informally (intermediate results), provided that they synchronize at some point in order to get back to some consistent state from the concurrency and process point of views ( nal result). Thus we allow users to break isolation and consistency providing that at some time, they pay the price and do some work to reestablish isolation and consistency. We expect that this approach is viable in design environments as it is the case in software development. We have also pointed out the synergy which exists between synchronization and constraints checking. Sometimes, constraints checking triggers some information exchange between activities that will avoid subsequent process iteration; sometimes, cooperation is used to allow to validate constraints that could not be validated by an activity alone. The feasibility of the approach has been proved by a prototype implementation that integrates the Coo-protocol and constraints checking. Today, we are designing a new version of the prototype that will be easier to deploy in order to conduct middle scale experimentation of the approach in 19

software development and in other domains[22]. This will help us to assess the approach and to identify more precisely actual user needs.

References 1. A.K. Elmagarmid, editor. Database transaction models for advanced applications. Morgan Kau man, 1992. 2. G. Junkerman, B. Peushel, W. Schafer, and S. Wolf. MERLIN : Supporting Cooperation in Software Development Through a Knowledge Based Environment. In J. Kramer A. Finkelstein and B. Nuseibeh, editors, Software Process Modelling and Technology. Research Study Press, 1994. 3. N. Belkhatir and J. Estublier. ADELE{TEMPO : An Environment to Support Process Modelling and Enaction. In J. Kramer A. Finkelstein and B. Nuseibeh, editors, Software Process Modelling and Technology. Research Study Press, 1994. 4. N. Barghouti. Supporting Cooperation in the MARVEL Process-Centered SDE.

Proceedings of the Fifth ACM SIGSOFT Symposium on Software Development Environments, 17(5):21{31, December 1992. 5. A. Clarke. A Theoretical Model of Cooperation. In Proc. 2nd International Conference on the Design of Cooperative Systems (COOP'96), Juan-les-Pins,

France, june 1996. 6. K. Ramamritham and P.K. Chrysanthis. A taxonomy of correctness criteria in database applications. The VLDB Journal, 5:85{97, 1996. voir ramamritham93. 7. P. Molli. COO-Transaction: Enhancing Long Transaction Model with Cooperation. In 7th Software Con guration Management Workshop (SCM7), LNCS, Boston, USA, May 1997. 8. J. Gray and A. Reuter. Transaction Processing: Concepts and Techniques. Morgan Kaufmann, 1993. 9. A.K. Elmagarmid, Y. Leu, J.G. Mullen, and O. Bukhres. Introduction to Advanced Transaction Models. In A.K. Elmagarmid, editor, Database transaction models for advanced applications. Morgan Kau man, 1992. 10. S. Dart. Spectrum of functionality in con guration management systems. Technical Report CMU/SEI-90-TR-11, Software Engineering Institute, Carnegie Mellon University, Pittsburgh, Pennsylvania 15213, December 1990. 11. U. W. Lipeck. Stepwise Speci cation of Dynamic Database Behaviour. In ACM SIGMOD, pages 387{397, 1986. 12. U. W. Lipeck and M. Gertz. Transitional Mointoring of Dynamic Integrity Constarints. Bulletin of the Technical Committee on Data Engineering, IEEE Computer Society, 17(1):38{42, June 1994. 13. E. Allen Emerson. Temporal and Modal Logic, chapter 16, pages 977{1069. Handbook of the Computer Science. Elsevier Sciences B.V., 1990. 14. H. Skaf, F. Charoy, and C. Godart. Maintaining Consistency of Cooperative Software Development Activities. In 6th International Workshop on Foundations of Models and Languages for Data and Objects, pages 103{118, Schloss Dagstuhl, Germany, september 1996. 15. P.W. Grefen and P.M. Apers. Integrity Control in Relational Database Systems { An Overview. Data and Knowledge Engineering, 10(2), pages 187{223, 1993. 16. C. Godart. COO: a Transaction Model to support COOperating software developers COOrdination. In 4th European Software Engineering Conference (ESEC4), Garmisch, LNCS 717, 1993. 17. G. Canals, P. Molli, and C. Godart. Concurrency control for cooperating software

20

processes. In Proceedings of the 1996 Workshop on Advanced Transaction Models and Architecture (ATMA'96), Goa, India, 1996.

18. U. W. Lipeck. Transformation of Dynamic Integrity Constraints into Transaction Speci cations. In North-Holland, editor, Theoretical Computer Science, pages 115{142, 1990. 19. H. Skaf, F. Charoy, and C. Godart. A Hybrid Approach to Maintain Consistency of Cooperative Software Development Activities. In The Ninth International Conference on Software Engineering and Knowledge Engineering, SEKE'97, Madrid, 1997. 20. Hala Skaf. Une approche hybride pour gerer la coherence dans les environnements de developpement cooperatif. These en informatique, Universite de Nancy I { Centre de Recherche en Informatique de Nancy, 1997. 21. C. Godart, G. Canals, F. Charoy, P. Molli, and H. Skaf. Designing and Implementing COO: Design Process, Architectural Style, Lessons Learned. In International Conference on Software Engineering (ICSE18), 1996. IEEE Press. 22. K. Benali, M. Munier, and C. Godart. Cooperation models in co-design. In Concurrent Engineering Symposium, SAE, Detroit, february 1998.

21