Chapter 14. Typed Group Communication

14.1. Overview

Group communication is a crucial feature for high-performance and Grid computing. While previous works and libraries proposed such a characteristic (e.g. MPI, or object-oriented frameworks), the use of groups imposed specific constraints on programmers, for instance the use of dedicated interfaces to trigger group communications.

We aim at a more flexible mechanism. We propose a scheme where, given a Java class, one can initiate group communications using the standard public methods of the class together with the classical dot notation; in that way, group communications remains typed.

In order to ease the use of the group communication, we provide a set of static methods on the ProActiveGroup class and a set of methods on the Group interface.

Here, a short compilation about the syntax and some method used in the Group Communication API is presented. More informations follow.

   // created at once, 
   // with parameters specified  in params,
   // and on the nodes specified in nodes
A ag1 = (A) ProActiveGroup.newGroup( 'A', params, [nodes]);
   // A general group communication without result
   // A request to foo is sent in parallel to all active objects 
   // in the target group (ag1)
ag1.foo(...);
   // A general group communication with a result
V vg = ag1.bar(...);
   // vg is a typed group of 'V': operation 
   // below is also a collective operation
   // triggered on results
vg.f1();

14.2. Creation of a Group

Any object that is reifiable has the ability to be included in a group. Groups are created using the static method ProActiveGroup.newGroup. The common superclass for all the group members has to be specified, thus giving the group a minimal type.

Let us take a standard Java class:

class A { 
  public A() {}
  public void foo (...) {...}
  public V bar (...) {...}
  ...
}

Here are examples of some group creation operations:

   // Pre-construction of some parameters: 
   //   For constructors:
Object[][] params = {{...} , {...} , ... };
   //   Nodes to identify JVMs to map objects
Node[] nodes  = { ... , ..., ... };
   // Solution 1: 
   // create an empty group of type 'A'
A ag1 = (A) ProActiveGroup.newGroup('A');
   // Solution 2: 
   // a group of type 'A' and its members are 
   // created at once, 
   // with parameters specified  in params,
   // and on the nodes specified in nodes
A ag2 = (A) ProActiveGroup.newGroup('A', params, nodes);
   // Solution 3: 
   // a group of type 'A'  and its members are 
   // created at once, 
   // with parameters specified in params,
   // and on the nodes directly specified 
A ag3 = (A) ProActiveGroup.newGroup('A', params[], 
                   {rmi://globus1.inria.fr/Node1,
                    rmi://globus2.inria.fr/Node2});

Elements can be included into a typed group only if their class equals or extends the class specified at the group creation. For example, an object of class B (B extending A) can be included to a group of type A. However based on Java typing, only the methods defined in the class A can be invoked on the group.

14.3. Group representation and manipulation

The typed group representation we have presented corresponds to the functional view of groups of objects. In order to provide a dynamic management of groups, a second and complementary representation of a group has been designed. In order to manage a group, this second representation must be used instead. This second representation, the management representation, follows a more standard pattern for grouping objects: the Group interface.

We are careful to have a strong coherence between both representations of the same group, which implies that modifications executed through one representation are immediately reported on the other one. In order to switch from one representation to the other, two methods have been defined : the static method named ProActiveGroup.getGroup, returns the Group form associated to the given group object; the method getGroupBytype defined in the Group interface does the opposite.

Below is an example of when and how to use each representation of a group:

   // definition of one standard Java object
   // and two active objects
A a1 = new A();
A a2 = (A) ProActive.newActive('A', paramsA[], node);
B b  = (B) ProActive.newActive('B', paramsB[], node);
   // Note that B extends A
   // For management purposes, get the representation
   // as a group given a typed group, created with
   // code on the left column:
Group gA = ProActiveGroup.getGroup(ag1);
   // Now, add objects to the group:
   // Note that active and non-active objects 
   // may be mixed in groups
gA.add(a1);
gA.add(a2);
gA.add(b); 
   // The addition of members to a group immediately
   // reflects on the typed group form,  so a method
   // can be invoked on the typed group  and will
   // reach all its current members
ag1.foo(); // the caller of ag1.foo() may not belong to ag1
   // A new reference to the typed group  
   // can also be built as follows
A ag1new = (A) gA.getGroupByType();

14.4. Group as result of group communications

The particularity of our group communication mechanism is that the result of a typed group communication is also a group. The result group is transparently built at invocation time, with a future for each elementary reply. It will be dynamically updated with the incoming results, thus gathering results. Nevertheless, the result group can be immediately used to execute another method call, even if all the results are not available. In that case the wait-by-necessity mechanism implemented by ProActive is used.

   // A method call on a group, returning a result
V vg = ag1.bar();
   // vg is a typed group of 'V': operation 
   // below is also a collective operation
   // triggered on results
vg.f1();

As said in the Group creation section, groups whose type is based on final classes or primitive types cannot be built. So, the construction of a dynamic group as a result of a group method call is also limited. Consequently, only methods whose return type is either void or is a 'reifiable type', in the sense of the Meta Object Protocol of ProActive, may be called on a group of objects; otherwise, they will raise an exception at run-time, because the transparent construction of a group of futures of non-reifiable types fails.

To take advantage with the asynchronous remote method call model of ProActive, some new synchronization mechanisms have been added. Static methods defined in the ProActiveGroup class enable to execute various forms of synchronisation. For instance: waitOne, waitN, waitAll, waitTheNth, waitAndGet. Here is an exemple:

   // A method call on a typed group
V vg = ag1.bar(); 
   // To wait and capture the first returned 
   // member of vg
V v = (V) ProActiveGroup.waitAndGetOne(vg);
   // To wait all the members of vg are arrived
ProActiveGroup.waitAll(vg);

14.5. Broadcast vs Dispatching

Regarding the parameters of a method call towards a group of objects, the default behaviour is to broadcast them to all members. But sometimes, only a specific portion of the parameters, usually dependent of the rank of the member in the group, may be really useful for the method execution, and so, parts of the parameter transmissions are useless. In other words, in some cases, there is a need to transmit different parameters to the various members.

A common way to achieve the scattering of a global parameter is to use the rank of each member of the group, in order to select the appropriate part that it should get in order to execute the method. There is a natural traduction of this idea inside our group communication mechanism:the use of a group of objects in order to represent a parameter of a group method call that must be scattered to its members.

The default behaviour regarding parameters passing for method call on a group, is to pass a deep copy of the group of type P to all members. Thus, in order to scatter this group of elements of type P instead, the programmer must apply the static method setScatterGroup of the ProActiveGroup class to the group. In order to switch back to the default behaviour, the static method unsetScatterGroup is available.

   // Broadcast the group gb to all the members
   // of the group ag1:
ag1.foo(gb);
   // Change the distribution mode of the 
   // parameter group:
ProActiveGroup.setScatterGroup(gb);
   // Scatter the members of gb onto the 
   // members of ag1:
ag1.foo(gb);

To learn more, see the JavaDoc and the paper [BBC02].