Design and implementation of a programmable coordination architecture for mobile agents
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Design and Implementation of a Programmable Coordination
Architecture for Mobile Agents
Giacomo Cabri, Letizia Leonardi, Gabriele Reggiani, Franco Zambonelli Dipartimento di Scienze dell’Ingegneria – Università di Modena e Reggio Emilia E-mail: {giacomo.cabri, letizia.leonardi, reggiani, franco.zambonelli}@unimo.it
Abstract
The paper describes the design and the Java implementation of a coordination architecture for mobile agents, based on an object-oriented Linda-like tuple space model, compliant with the Sun's JavaSpaces specifications. Moreover, unlike Linda and JavaSpaces, the proposed architecture integrates a reactive model: the behaviour of the tuple spaces can be programmed by installing reactions which are triggered by the accesses of mobile agents to the tuple spaces. Reactions can increase the coordination flexibility and ease agent programming, as shown via an application example in the network management area.
1.Introduction
A mobile agent is an active object that can dynamically change its execution environment, i.e., its node of execution, to carry out distributed tasks on behalf of its user [7, 8]. The interest in the mobile agent paradigm is justified by the advantages it provides over traditional approaches in Internet applications: (i) mobile agents can save bandwidth, by moving locally to the resources they need; (ii) mobile agents can carry the code to manage remote resources and do not need the remote availability of a specific server; (iii) mobile agents do not require continuous network connection, because interacting entities can move to the same site when the connection is available.
Mobile agent applications are intrinsically collaborative, since they are typically made up of several active objects, which roam the Internet to access the available services and information, and which are in need of coordinating their activities – both with each other and with their hosting environments – to achieve the application goal. Therefore, the adoption of a suitable coordination model is a fundamental choice. In [3], we argue that traditional object-oriented coordination models based only on method invocations and derived from the client-server model, may suffer of several limitations when mobile application components are involved. Instead, fully uncoupled (Linda-like) coordination models based on the tuple space concept –by enforcing anonymous and asynchronous interactions – intrinsically suit the openness and the heterogeneity of the Internet scenario, as well as the presence of mobile application entities. This is confirmed by several proposals in this area, which adopt uncoupled coordination models [2] or, specifically, Linda-like coordination models [6, 12].
The Linda’s limited flexibility in interactions, caused by the statically defined coordination laws based on associative accesses to the tuple space, can be easily overcome by the definition of a programmable coordination model. The programmability of tuple spaces permits to change the semantics of the interactions to meet specific needs, either of the application agents or of the execution environments. The above considerations motivate the implementation of the MARS (Mobile Agent Reactive Spaces) coordination architecture [4], based on the definition of object-oriented Linda-like tuple spaces [1], associated to each execution environment. Mobile agents can exploit tuple spaces for inter-agent communication, by using them to read and write the messages they want to exchange, in the form of tuples. In addition, a mobile agent can retrieve from a tuple space primitive data items and references to objects that represent
execution environment resources. Moreover, unlike raw Linda-like tuple spaces, MARS tuple spaces can be meta-level programmed (either by the local administrator or by the agents themselves) to react with specific actions to the accesses made to them by agents. This characteristic of MARS grants further flexibility in mobile agent applications, by allowing to define specific and stateful coordination policies and to enforce secure agent execution.
The aim of this paper is to describe the design and the Java implementation of the MARS reactive coordination architecture. We have chosen Java because the most mobile agent systems are written in Java, to exploit its support to distributed environments and code mobility [8].However, since Java is not specifically designed to program mobile agents, we go deeper by pointing out the implementation choices and the peculiar problems we faced in our implementation work. To clarify the features of MARS, and to show its flexibility and ease of use, we exploit some application examples in the network management area.
2. The MARS Architecture
The MARS (M obile A gent R eactive S paces) system implements a portable and programmable coordination architecture – based on object-oriented tuple spaces – for mobile agents. MARS is available for downloading at the MOON project home page [11].
MARS has been designed to be loosely coupled to the underlying mobile agent system, and it is not bound to any specific mobile agent system implementation [4]. We have tested MARS on different Java-based mobile agent systems, such as Aglets [10] and SOMA [14]. When an agent arrives on a node (step a of figure 1), the local mobile agent server – in charge of accepting and executing it – simply supplies to the agent a reference to a local MARS tuple space (step b of figure 1). Then, the agent is enabled to access the tuple space to read, extract and put tuples (step c in figure 1). Though in MARS agents access to the tuple space always with the same basic set of operations (Linda-like), the behaviour of such operations can be dynamically changed by associating specific reactions (step d in figure 1), as better described in the following.
a
Agent
Figure 1. The MARS Architecture (smiles represent mobile agents)
2.1 MARS Tuple Spaces
MARS has been designed in compliance with the JavaSpaces specification [9]. Therefore, as in JavaSpaces, MARS tuples are Java objects, instances of tuple classes. A tuple class can either implement the Entry interface or derive from the AbstractEntry class (that defines the basic tuple properties by implementing the Entry interface) and defines, as public instance variables,the specific tuple fields. Each field of the tuple is a reference to an object that can also represent primitive data type (enclosed in wrapper objects). A field of a tuple can have either a defined (actual) or a null (formal) value; a tuple with at least one formal value is called
template tuple.
Each MARS tuple space is realised as a Java object, instance of the Space class, which implements the MARS interface (figure 2). Five operations are provided to access the tuple space: write puts a tuple, supplied as the first parameter, in the space; read retrieves a tuple from the space, matching with the template tuple supplied as the first parameter; take works as read but also extracts the matching tuple from the space; readAll retrieves all matching tuples from the space; takeAll extracts all matching tuples from the space.
F or all the operations, the second txn parameter can specify a transaction the operation belongs to. The last timeout parameter of read, take, readAll and takeAll, specifies the time to wait before the corresponding operation returns a null value if no matching tuple is found: NO_WAIT means to return immediately, 0 means to wait indefinitely. The lease parameter of the write operation sets the lifetime of the written tuple. Let us note that the readAll and takeAll operations, not present in the JavaSpace interface, have been added for flexibility's sake.
F igure 2. The MARS interface
T he pattern matching rules must take into account that the elements of a tuple can be non-primitive objects. Then, as in Javaspaces, a template tuple TMPL and a tuple T match if and only if:
•TMPL is an instance of either the class of T or of one of its superclasses; this extends the Linda model according to object-orientness by permitting a match also between two tuples of different types, provided they belong to the same class hierarchy;
•the defined fields of TMPL that represent primitive types (integer, character, boolean, etc.) have the same value of the corresponding fields in T;
•the defined non-primitive fields (i.e., objects) of TMPL are equal – in their serialised form –to the corresponding ones of T (two Java objects assume the same serialised form only if each of their instance variables have equal values, recursively including enclosed objects).
Once a tuple is obtained from the space, its actual field objects can be accessed as any other Java object.
2.2An Application Example in the Network Management
A very interesting application area for mobile agents is decentralised network management systems [13]: agents can roam in a network to carry out their tasks on its nodes. To this end, agents need to access node resources and to interact with other agents. The adoption of tuple spaces as coordination means provides agents with a uniform interface to handle local resources, to retrieve and store information and to interact with other agents.
With regard to node resources, a MARS tuple space can be devoted to store, among other possible information, the status of interesting network resources and, for instance, the information about the network link status. In every node, for each network link, the administrator can then store a tuple, instance of the LinkTuple class (see figure 3), in the local tuple space. When an agent with manager role arrives at a node, it can discover the local topology status by asking the tuple space for such tuples.
Figure 3. The code of a tuple that represents a network link
As an example of the pattern matching mechanism previously described, the template tuple (“link”, null, null) matches with the tuple (“link”, polaris.dsi.it, true) and also with (“link”, sirio.dsi.it, false);a template tuple (“link”, null, true) matches only with the former tuple.
In addition, a tuple space can be exploited by agents to communicate by exchanging messages – for instance, containing the results of even complex computation – in the form of tuples that are stored by the senders and retrieved by the receivers.
MARS is provided with a WWW interface to facilitate the administration task; in particular a dialog window permits to insert tuples in one tuple space (figure 4-left), while another dialog permit to insert reactions in one meta-level tuple space (figure 4-right).
Figure 4. The MARS user interface to manage tuples (left) and reactions (right)
2.3Serialised Form, Matching Mechanism and Class Loading
According to the JavaSpaces specifications, tuple objects are not directly written into a MARS tuple space, but they are converted in particular objects that contain the serialised form of each field of the tuple and the serialised form of the class of the tuple. In particular, the serialised form of tuple fields allows the pattern matching mechanism to verify if two objects are equal (i.e. they have the same value), by comparing (bit to bit) the serialised forms of the fields. In fact, the comparison of the serialised forms allows knowing if two objects have the same Java class, and if all the primitive attributes of each level have the same value. The serialised form of the class is used to check if the class of the template matches with the class of the stored tuple, since, after the separate serialisation of the fields, the information about the class of the tuple object is lost. The comparison between the serialised class of the stored tuple and the template tuple allows finding out also whether the template tuple class is a superclass of the stored tuple class.
When an agent obtains a tuple stored in the space, it is necessary to transform this tuple from the stored form to the original form. To execute the deserialisation operation, MARS has to retrieve the class of the tuple object.
Let us suppose that a reader agent invokes a read operation with the template tuple TMPL, where TMPL is an instance of the LinkTuple class, with three fields that have values “link”, null and
null, as in the following fragment of code:
L inkTuple TMPL, T;
T MPL = new TupleExample(“link”, null, null);
T = (LinkTuple)LocalSpace.read(TMPL,..,..);
To retrieve the class of the read tuple, the pattern matching mechanism verifies that the class of the template is the same (or a superclass) of the class of the matching tuple by using the stored serialised form of the class without problems. However, the casting operation performed in the code of the reader agent on the object returned from the read operation, would throw a ClassCastException exception. In fact, if the class of the returned object has been loaded by the writer agent Class Loader, it should be different from the one deriving from the class used in the casting action, which has been loaded by the reader agent Class Loader. When two different Class Loader CL1 and CL2 load a class (creating the object form of the class) even from the same file .class, two distinct class C1 and C2 are obtained, so an instance of the class C1 is not castable by the class C2.
The above observation justifies the approach chosen in the implementation of MARS, where the deserialisation operation loads the tuple classes using the Class Loader of the reader agent.
The case when a template matches a tuple whose class is a subclass of the class of the template is more complex. In fact, it is possible that the class of the tuple is not available at the reader’s Class Loader. So MARS, when executes the deserialisation operation, asks reader’s Class Loader for the most specialised super-class of the class of the tuple that is available, at least the class of the template itself. Obviously, the fields included in the selected tuple that are not included in the class returned by the Class Loader, are not returned to the reader agent. This choice is semantically correct, because if an agent asks for a specific information, it wants to receive only the requested information. Therefore, if an agent invokes a read or take operation with a template TMPL having a specific class, it requires only the values of the fields of TMPL. At this point it is clear that if the template TMPL matches with a tuple T having as class a subclass of TMPL, the only values to be returned are the values of the fields of T that are also fields of TMPL.
If an agent needs the complete form of the matching tuple, the deserialisation operation asks the writer agent Class Loader for the class of the tuple. It is important to note that in this case the fields of the returned tuple are not accessible using the dot notation, so the only way to access them is to use the Reflection methods.
3.The MARS Reactive Model
Unlike the Linda model, MARS permits to associate programmable reactions to the tuple space accesses performed by agents. We implemented reactions as stateful Java objects that have to be instances of classes that derive from the Reactivity abstract class shown in figure 5.
Figure 5. The Reactivity class
Reactions have access to tuple spaces and can perform any kind of operation on them. This can be used to exploit the tuple spaces as repositories of reaction state information, in addition to the state that the reaction object can store as any other Java object. Also, reactions, as they are executed, have the availability of the result of the matches issued by the associated
operation.
From the previous considerations, it follows that reactions can influence the semantics of operations by returning to the invoking agent tuples different than the ones resulting from the basic pattern matching mechanism, or modifying the actions of the operations (possibly replacing the operations themselves). The above characteristics distinguish the MARS approach from the notify mechanism of JavaSpaces, which is simply a way to make external entities aware of matches in the tuple space and influences neither the built-in pattern matching mechanism nor the semantic of the operations.
Another important characteristic of the reactions is that they are composed by two programmable parts: a procedure part and a thread part. The procedure part is executed in the execution flow of the operation that triggers the reaction, so the operation cannot terminate until the reaction is terminated too. Differently, the execution flow of the thread part is concurrent with the execution flow of the operation. So the reaction can stop and can resume its activity also when the operation is terminated. Of course, only the procedure-part of the reaction can return to the triggering operation the information required modifying its result and effect. The procedure part is implemented by the reaction method, while the thread part is implemented by the method run, which the Reactivity class defines to implement the Runnable interface. The programmer of the reaction can re-define the method bodies to specify the reaction behaviour in a subclass of the Reactivity class. Both methods are executed when the reaction is triggered, but one of the methods can even do nothing if the programmer does not re-define the corresponding body, being she/he not interested in exploiting its features.
3.1The Meta-level Associative Mechanism
The association of reactions to access events is dealt with meta-level tuples (meta-tuples for short) with five components. The resulting meta-level tuple space is based on a Linda-like associative mechanism similar to the one of the base-level tuple space. A meta-tuple (possibly with some non-defined values) associates a reaction to all the access events that matches the meta-tuple itself. Putting and extracting meta-tuples from the meta-level tuple space (for instance, with the help of the dialog window of figure 4-right) provide to install and uninstall, respectively, reactions.
The five components to be considered when associating reactions to access events are: Reaction (Rct), Tuple item (T), Operation type (O), Agent identity (I), Triggering position (P). The reaction (i.e., the methods of the reaction object Rct) is executed when an agent with identity I invokes the operation O on a tuple matching T. To retrieve a reaction, MARS performs a read operation in the meta-level tuple space with the meta-tuple (Rct, T, O, I, P), using the meta-level-read() method shown in the next paragraph. The pattern matching mechanism of the meta-level tuple space is exactly the one used in the base-level tuple space, but it is important to note that the stored meta-tuples play now the role of templates. In this way, MARS permits the association of a reaction to a specific tuple, to all tuples, or to the tuples of a given class, as better shown in the example section.
The last component of one meta-level tuple specifies the reaction triggering position inside the execution flow of the operation. The reaction can be programmed to be triggered before the core of the operation (pre-reaction), after the core of the operation (post-reaction), or between two steps of the core of the operation in case of multi-step operations (infra-reaction).
Table 1 shows the characteristics of the different reaction kinds. For each operation, and for each triggering position, the table reports when the reaction is triggered inside the operation execution flow, which tuple item is used in the meta-tuple meta-level pattern matching to retrieve the reaction code, and which effects the reaction can have. For homogeneity’s sake, each kind of operation can have a pre, an infra and a post reaction, even if in the case of a write operation, the infra-reaction and the post-reaction type become the same reaction type.
Moreover, for a write operation the tuple used in the meta-tuple is always the one written by the agent and the reaction cannot imply any modification to the result of the operation, because the write operation does not return any tuple.
Table 1. Classification of the reactions
We consider an input operation to explain the three possible triggering positions. The execution of a pre-reaction substitutes the operation and decides its effects and its result. The tuple item used in the reaction pattern matching mechanism is the template passed to the operation (because no other tuple of the space has been involved until that moment). An infra-reaction can modify the result of the operation by acting on the matching tuple at the previous step. This tuple is also used in the pattern matching to find a reaction to be executed. Finally, the tuple item used in the post-reaction pattern matching is the template of the operation, and the reaction can modify the result of the operation acting on all the matching tuples.
For instance, the meta-tuple (ReactionObj, null, read, null, “post-reaction”) inserted in the meta-level tuple space associates the ReactionObj to all read operations disregarding the peculiar type/class and content of the tuple, and the agent identity. The fifth component specifies that the reaction has to be a post-reaction (invoked after the retrieving of the matching tuple).
Figure 6. The pseudo code of the readAll operation
3.2The Trigger Algorithm
The meta-level tuple spaces are composed of meta-tuples (Rct, T, O, I, P). For any access to
the base-level tuple space, a pattern matching is activated on the meta-level space to check for
the presence of reactions to be executed; for each matching tuple the corresponding reaction is
triggered. In order to explain how the executions of the reactions are interleaved in the
execution of the operation, we describe the trigger algorithm. To this purpose we exploit the
figure 6 that shows the pseudo code of the readAll operation.
In this pseudo code the core of the operation is represented by the base-level-read() method
that gets the tuple matching with the template tmpl from the tuple space; the template of the base-level-read() is the template of the readAll operation. To avoid endless recursions, the operations on the base-level tuple space performed within a reaction do not issue any reaction.
The presence of associated reactions is checked by the meta-level-read() methods, which gets
the matching meta-tuple from the meta-level tuple space. The fields of the meta-level-read() tuple
specify the current event, to search for a reaction associated to it. In particular, the GetAgentIdentity() method is used to ask the mobile agent system for the identity of the agent. The found reaction is triggered by the Execute method.
An analogous pseudo code can be written for the other operations, using the corresponding
base-level operations, while the searching for reactions is always dealt by a meta-level-read.
3.3Examples of Reactions in Network Management Applications
The use of MARS as a repository for network management related information, sketched in
the paragraph 2.2, can be improved by reactions: they can be exploited to provide useful
services in order to manage even complex information. Let us consider the problem of
managing the frequent modifications – due to changes of the network – of the status of network
resources represented by tuples stored in the tuple space. The trivial solution to update the
interested tuples as soon as the value changes is not the preferable one, because of the possible
high overhead if such changes occur very often. A less intrusive solution can be based on a
reaction that dynamically evaluates and computes tuples, retrieving the current status of the
network only when they are requested by an agent. In other words, the reaction hides a service
devoted to monitoring the resource status and providing it to agents. From the agents’
perspective, there is not awareness of the job of reactions, and the data is retrieved in the most
natural way.
Figure 7. The UpdateLink reaction class
The meta-tuple that associates such a reaction to the read accesses is (ReactionObj, (“link”, null, null), read, null, “infra-reaction”), where ReactionObj is an instance of the UpdateLink class (figure 7). In this case, it is useful to trigger the reaction every time a matching tuple is found, and to pass
such tuple as a parameter. Setting the fifth field of the meta-level tuple to infra-reaction admits the issuing of the reaction only when a link tuple has matched.
In addition, a reaction can be used to implement security polices. For instance, a reaction can check if an agent has the rights to perform a read operation. In this case, the reaction must be triggered before actually retrieving tuples from the space, to avoid useless executions of code if the agent is not allowed; so the reaction must be installed as pre-reaction by storing the meta-tuple (ReactionObj, (“system information”, null, null), read, null, “pre-reaction”). The association of this reaction to the tuple space that maintains system information, grants full rights to the system administrator, while denies other agents to read private information. Even if this example is quite simple, a reaction can generally define very complex security policies.
Finally, a post-reaction can be used if the programmer wants to do something to finalise the associated operation. To illustrate such a kind of reaction, let us consider agents with a writer identity that are authorised to write tuples in the tuple space. However, this makes a node at risk of being overwhelmed of tuples left by agents that no one will ever use and that no one will ever worried to delete from the tuple space. Then, the administrator could decide to delete these tuples after they have been in the tuple space for a time longer than an allowed lifetime. In this case, the reaction thread part is exploited. The used reaction object is an instance of the LifeTime class, which defines the method run in order to sleep for the given lifetime and to delete the corresponding tuple at its awakening. The meta-tuple (ReactionObj, null, write, “writer”, “post-reaction”) can be used to associate this reaction to all write operations performed by the agents with a writer identity.
The above examples show reactions installed by the administrator, but MARS gives also the agents the capability of installing their own reactions; by exploiting this feature, the programmer of agent-based applications can adapt the behaviour of the tuple spaces to the application needs.
3.4The Lower-level Access Methods and Tuple Locking
Differently from the most of the non-reactive coordination spaces, MARS implements the operations in a non-atomic way, adopting an approach based on lower-level access methods and tuple locking. These choices avoid deadlocks and enhance the concurrency of the system.
If the operations are executed in an atomic way, only one operation at a time can be executed. This situation does not create any problem in the case the original semantics of the Linda operation is preserved. Instead, in case of reactive tuple space, the atomicity can provoke deadlocks. In fact, a reaction invoked inside an atomic operation can block the whole system and make impossible further accesses to the space, if it includes an endless cycle or a blocking instruction (such as a Java wait). Therefore, we decided to implement non-atomic operations.
The MARS operations are implemented using lower-level access methods (such as the base-level-read mentioned above) that are executed, instead, in an atomic way; the reactions are issued before and after the invocation of such methods. The effect of this approach is that the execution of a blocking reaction inside an operation, blocks the execution flow of the agent that has invoked the operation, but permits other agents to access the tuple space.
The enhancement of system concurrency is obtained by letting the lower-level access methods performed within a operations of different agents be interleaved in the execution flow. For example, the base-level-write method and the post-reaction of a write operation performed by the agent A and the take operation performed by the agent B, could be executed in the sequence showed in figure 8. This example shows that the approach we have chosen could generate a side effect: the tuple written by the agent A could be deleted by the agent B before the issuing of the agent A post-reaction. Because it is frequent that the reactions of an operation use in their activities the tuples handed (selected/inserted) by the operation, the previous situation must be avoided. Consequently, we have decided to introduce a lock mechanism on tuples. The tuple。