GRID computing is now a key aspect, from scientific to business applications, from large scale simulations to everyday-life enterprise IT, including telcos and embedded domains. We are just entering the era of Ubiquitous Computing with many computers at hand of every single individual - after the old days of mainframes and servers, hundreds of persons sharing the same machines, and the quite current days of PCs, one person/one computer. Potentially spanning all over the world, involving several thousands or several hundred thousands of nodes, the programming of Grid applications call for a new paradigms. The ProActive Grid solution relies on systematic asynchronous method calls, allowing to master both complexity and efficiency.
Overall, ProActive promotes a few basic and simple principles:
Activites are distributed, remotely accessible objects
Interactions are done through asynchronous method calls
Results of interactions are called futures and are first class entities.
Callers can wait for results using a mechanism called wait-by-necessity
ProActive takes advantage of this sound programming model, to further propose advanced features such as groups, mobility, and components. In the framework of a formal calculus, ASP (Asynchronous Sequential processes), confluence and determinism have been proved for this programming model: CH05 and CHS04.
Asynchronous method calls with returns lead to an emerging abstraction: futures, the expected result of a given asynchronous method call. Futures turn out to be a very effective abstraction for large distributed systems, preserving both low coupling and high structuring.
Asynchronous method calls and first-class futures are provided in the unifying framework of an Active Object.
Most of the time, activities and distribution are not known at the beginning, and change over time. Seamless implies reuse, smooth and incremental transitions.
A huge gap still exists between multithreaded and distributed Java applications which impedes code reuse in order to build distributed applications from multithreaded applications. Both JavaRMI and JavaIDL, as examples of distributed object libraries in Java, put a heavy burden on the programmer because they require deep modifications of existing code in order to turn local objects into remotely accessible ones. In these systems, remote objects need to be accessed through some specific interfaces. As a consequence, these distributed objects libraries do not allow polymorphism between local and remote objects. This feature is our first requirement for a Grid Computing framework. It is strongly required in order to let the programmer concentrate first on modeling and algorithmic issues rather than lower-level tasks such as object distribution, mapping and load balancing.
Active Objects
are the core of the ProActive
computing concept. An Active Object is both a Remote
Object (which allows to deploy it on a distant host) and a
Thread (which gives it its own activity, its own
independant behaviour and in concurrency with other Active Objects
deployed). Given a standard object, turning it into an Active Objects
provides:
location transparency
activity transparency
synchronization
Communications to an active object are by default asynchronous. So, an active object is: a main object + a single thread + a queue of pending requests. As such, a reference to a remote object is equivalent to a reference to a remote activity. An activity is an object ; but being in a non-uniform model, not all objects are active objects, the majority remaining standard Java objects. As there cannot be any sharing, an active object is also a unit of computational mobility (see Chapter 16, Active Object Migration).
Note | |
---|---|
The |
On activation, an object becomes a remotely accessible entity with
its own thread of control: an active object. Here are given as example
three ways to transform a standard Object
into an
Active Object
:
Object[] params = new Object[] { new Integer (26), "astring" }; A a = (A) ProActive.newActive("example.A", params, node);
Example 1.1. Class-based Active Object
public class AA extends A implements Active {} Object[] params = new Object[] { new Integer (26), "astring" }; A a = (A) ProActive.newActive("example.AA", params, node);
Example 1.2. Instantiation-based Active Object
Object-based Active Objects
Allows to turn active
and set remote objects for which you do not have the source code; this is
a necessary feature in the context of code mobility.
A a = new A (26, "astring"); a = (A) ProActive.turnActive(a, node) ;
Example 1.3. Object-based Active Object
Note | |
---|---|
Nodes allow to control the mapping to the hosts. See Section 13.1.2, “Using a Node” for an example use of a Node, and Section 21.2, “Principles” for a definition. |
Here is a summary of the computation model being used by ProActive:
Heterogeneous model both passive and active objects
Systematic asynchronous communications towards active objects
No shared passive object , Call-by-value between active objects
Automatic continuations , a transparent delegation mechanism
wait-by-necessity , automatic and transparent futures
Centralized and explicit control , libraries of abstractions
To compare to Java RMI, a Java remote object is not by essence an
activity. The fact that several threads can execute several remote method
calls simultaneously within a remote object does reveal that facet. When
writing ro.foo(p);
, what ro identifies is not a remote
activity, but just a remote object. This has several consequences, along
with the presence of sharing between remote objects that prevents them
from being a unit of computational migration.
Two key features:
Wait-by-necessity: inter-objects synchronization. Systematic, implicit and transparent futures. Ease the programming of synchronization and reuse of existing methods
Polymorphism between standard and active objects
Type compatibility for classes and not just for interfaces
Needed and done for the future objects as well
Dynamic mechanism (dynamically achieved if needed)
This example implements the smallest program in ProActive. This is the easiest program you could write, using the Active Object concept. This is just to show quickly how code can be written, with minimal knowledge of the API.
You can get a more complete 'hello world' example, with deployment on a remote host, further on in the manual (Section 13.10, “The Hello world example”).
A client object displays a String
received from
elsewhere (the original VM). This illustrates the creation of an Active
Object.
Only one class is needed: we have put the main method inside the class, which when deployed will be an Active Object.
This class can be used as an Active Object, serving requests. Its creation involves the following steps:
Provide an implementation for the required server-side functionalities
Provide an empty, no-arg constructor
Write a main
method in order to
instantiate one server object.
public class TinyHello implements java.io.Serializable { static Logger logger = ProActiveLogger.getLogger(Loggers.EXAMPLES); private final String message = "Hello World!"; /** ProActive compulsory no-args constructor */ public TinyHello() { } /** The Active Object creates and returns information on its location * @return a StringWrapper which is a Serialized version, for asynchrony */ public StringMutableWrapper sayHello() { return new StringMutableWrapper( this.message + "\n from " + getHostName() + "\n at " + new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new java.util.Date())); } /** finds the name of the local machine */ static String getHostName() { try { return java.net.InetAddress.getLocalHost().toString(); } catch (UnknownHostException e) { return "unknown"; } } /** The call that starts the Acive Objects, and displays results. * @param args must contain the name of an xml descriptor */ public static void main(String[] args) throws Exception { // Creates an active instance of class Tiny on the local node TinyHello tiny = (TinyHello) ProActive.newActive( TinyHello.class.getName(), // the class to deploy null // the arguments to pass to the constructor, here none ); // which jvm should be used to hold the Active Object // get and display a value StringMutableWrapper received = tiny.sayHello(); // possibly remote call logger.info("On " + getHostName() + ", a message was received: " + received); // potential wait-by-necessity // quitting ProActive.exitSuccess(); } }
Example 1.4. A possible implementation for the TinyHello
class
Implementing any remotely-accessible functionality is simply done
through normal Java methods in a normal Java class, in exactly the same
manner it would have been done in a non-distributed version of the same
class. Here, the only method is sayHello
Now that we know how to write the class that implements the
required server-side functionalities, let us see how to create the
server object. We want this active object to be created on the current
node, which is why we use newActive
with only two
parameters (done in the main
method).
The code snippet which instantiates the
TinyHello
in the same VM is the following (in the
main
method):
TinyHello tiny = (TinyHello) ProActive.newActive( TinyHello.class.getName(), // the class to deploy null // the arguments to pass to the constructor, here none ); // which jvm should be used to hold the Active Object
This is exactly like invoking a method on a local object of the same type. The user does not have to deal with catching exceptions related to the distant deployment.
As already stated, the only modification brought to the code by
ProActive is located at the place where active objects are created. All
the rest of the code remains the same, which fosters software reuse. So
the way to call the sayHello
method in this example
is the following (in the main
method):
StringMutableWrapper received = tiny.sayHello(); // possibly remote call logger.info("On " + getHostName() + ", a message was received: " + received); // potential wait-by-necessity
To launch the example, you may type:
linux> java -cp $CLASSPATH -Djava.security.policy=scripts/proactive.java.policy -Dlog4j.configuration=file:scripts/proactive-log4j org.objectweb.proactive.examples.hello.TinyHello
windows> java -cp $CLASSPATH -Djava.security.policy=scripts\proactive.java.policy -Dlog4j.configuration=file:scripts\proactive-log4j org.objectweb.proactive.examples.hello.TinyHello
There are also scripts in the scripts
directory:
linux> cd scripts/unix/ linux> tinyHello.sh
windows> cd scripts/windows windows> tinyHello.bat
[apple unix]tinyhello.sh --- Hello World tiny example --------------------------------- > This ClassFileServer is reading resources from classpath ProActive Security Policy (proactive.runtime.security) not set. Runtime Security disabled Created a new registry on port 1099 //apple.inria.fr/Node628280013 successfully bound in registry at //apple.inria.fr/Node628280013 Generating class: pa.stub.org.objectweb.proactive.examples.hello.Stub_TinyHello Generating class: pa.stub.org.objectweb.proactive.core.util.wrapper.Stub_StringMutableWrapper On apple/138.96.218.62, a message was received: Hello World! from apple/138.96.218.62 at 03/11/2005 14:25:32
© 2001-2007 INRIA Sophia Antipolis All Rights Reserved