Combining Mobile Agents with Persistent Systems - CiteSeerX

4 downloads 3003 Views 229KB Size Report
Mobile agents are active objects that migrate between programs. ... include local or remote database access. Free variables are also of interest, ... programming environment with: general and exible support for free variables; migration of code ...
Combining Mobile Agents with Persistent Systems: Opportunities and Challenges Miguel Mira da Silva

Malcolm Atkinson

Dept of Computing Science University of Glasgow Glasgow G12 8QQ, Scotland E-mail: fmms,[email protected]

Abstract. In the last three years we have been working with persistence and distribution, in particular migration of higher-level objects (such as procedures) between autonomous persistent programs. In this paper we introduce persistence and the suitability of Napier88 | the persistent system we have used for our experiments | as an agent language. We then present a few examples of opportunities and many more challenges that exist in the combination of persistence with agents.

1 Introduction Mobile agents are active objects that migrate between programs. These active objects are commonly implemented as procedures, instances of classes or abstract data types, or threads. A persistent program is a program written in a language that permits to create and manipulate objects independent of their life time (see section 2). The main motivation for this paper is our perception that free variables and persistence have not been properly addressed by the agent research community. Persistence is important because many of the examples presented in the agent literature include local or remote database access. Free variables are also of interest, and unavoidable in a persistent environment, because data and code are highly and strongly inter-connected in the persistent store (e.g., a procedure uses a large data structure or vice-versa). Java [61, 52] has been recently proposed as \the network language" because it was designed for migrating code between heterogeneous machines on the Internet. However, Java su ers from at least three limitations: 1) examples of Java applets are con ned to use the Java standard library; 2) since Java has no integrated persistent support, applets access databases in an ad-hoc manner; and 3) it is not possible to migrate complex data structures between Java programs in Java itself. There are no answers yet concerning the rst limitation. The second is partially solved by using a Java interface to access relational databases like JDBC [59]. In order to address the third limitation, Sun has proposed a CORBA-like RPC based on IDL [57] and an RMI (remote method invocation) system [58] on top of the Java system. Both are limited in the data types they can migrate and are not intended to transfer code (i.e., they do not replace the functionality provided by applets). This paper is based on our experience with persistent systems and higher-level distributed computation, two research areas that combined address many of the same issues as that of mobile agents. One of our goals is to o er the application programmer a general yet simple agent system that does not su er from any of the limitations with Java described above. Thus we aim at building a programming environment with: general and exible support for free variables; migration of code

and data in an integrated manner between autonomous programs; and provision for persistent agents to better access local and remote databases. In order to experiment our ideas we have used Napier88, a research orthogonally persistent programming language described in section 2. Napier88 and its extensive list of features have immensely helped our research. For example, we describe elsewhere how a type-safe persistent RPC was implemented in three months by the author alone [44]. This RPC has since then been continually extended and partially rebuilt, demonstrating how persistence and Napier88 are suitable for incremental program construction. Recently we have started to address mobile agents speci cally in our research work, a natural consequence of trying to support higher-order objects as arguments to remote procedures. In the process we have encountered some opportunities for combining persistence and agents that are described in section 3. However, we have also encountered many diculties and problems that are summarised as challenges in section 4. These are mostly a consequence of the rich type system provided by Napier88 and an orthogonal persistent system that maintains all relationships between data and code, safely and permanently. Throughout the paper we restrict our examples to the following agent systems: Java, Facile, Obliq, Mole, Tycoon and our own Napier88/RPC. This does not mean these systems are better or have more features than others, but simply that we had better access to their characteristics (i.e., material about them has been published and/or we have made contact with their authors). However, any mistakes and omissions are purely our fault.

2 Persistent Systems The persistence of an object is the period of time for which the object exists and is usable [1]. A persistent system ensures that objects remain available as long as they are required for computation, thus eliminating the need for les or databases (see gure 1 below). Persistent System Conventional Programmer

Program

Persistent Programmer

Store

Fig. 1. Architecture of a Persistent System A conventional, as opposed to persistent, programming language manipulates only objects which are resident in memory. If these objects are to be used later by the same or another program,

then the data has to be explicitly transfered from (volatile) program data structures to some sort of permanent (non-volatile) storage, generally utilising a di erent representation, naming scheme, access methods, etc. A persistent language avoids the need for the programmer to worry about these two worlds and to write code to transfer data between them. All code and all data are available for computation as long as they are required. This simplicity permits to use more much complex data structures because they do not have to be attened to a le or relational database. However, not all persistent languages o ers this extreme simplicity because there are increasing levels of commitment to the persistence abstraction. Orthogonal persistence [1, 7] is the most exigent and can only be achieved by applying three principles: persistence independence, i.e., programs look the same whether they manipulate short or long term data; data type orthogonality, i.e., there are no special cases for certain types [3]; and persistence identi cation, i.e., persistence is not related to the type system (as by inheriting from a persistent class as in ObjectStore [39]). The bene ts of orthogonally persistent systems, described extensively in the literature, have been summarised in a recent survey [7]. These are: increased programmer productivity; better data protection; long-term referential integrity; and incremental software construction. In short, orthogonally persistent systems are expected to provide better support for the design, development, operation and maintenance of complex database applications.

2.1 The Napier88 Persistent System Napier88 [49, 48] is a research persistent programming language that also incorporates a number of other interesting features (described below). Napier88 supports orthogonal persistence. Persistence of an object is de ned by reachability from a single persistent root. Objects that cannot be reached are unusable and thus can be garbage collected. The Napier88 rich type system is described by a set of base types and a set of constructors, and the recursive composition of these [16]. The language supports abstract data types [21] and parametric types, including parametric procedures. The type of an object can be obtained at run-time, and type equivalence is structural. (Napier88 has currently no support for inheritance but it has been recently proposed [17].) Procedures are rst-class objects in Napier88. This means procedures cannot only be declared, passed as parameters to other procedures, and executed, but also be assignable, the result of expressions or other procedures, elements of structures and vectors, and made persistent to survive program execution. First-class procedures can be used to implement abstract data types, modules, separate compilation, views and data protection [5]. Other features of Napier88 will be introduced in the next section as needed, including dynamic binding and type-checking, memory and disk garbage collection, type-safe linguistic re ection, heterogeneous architecture, and acceptable performance.

2.2 Napier88 Support for Agents Although Napier88 was not designed to be an agent language, not even to deal with distribution, Napier88 has many of the properties required for migrating code between programs. In order to demonstrate this claim, we use Knabe's list of essential and desirable properties for candidate agent languages [36]. (Knabe's original properties are summarised between quotation marks.)

Code Manipulation \The language must provide a means to identify the code of an agent, express that an agent should be transmitted, receive the agent and execute it within the same address space". Napier88 has support for all of these. Identity can be simply by variable name. For example, if we choose to implement agents as procedures, as Knabe does, then the name of a procedure identi es an agent. Procedures in Napier88 are rst-class objects, so they can be passed as arguments to other procedures (e.g., a migration procedure called hop as in Obliq). Napier88 also supports dynamic binding to objects in the persistent store so new procedures can be incorporated into the current execution. Knabe adds \allow code to be manipulated completely within the language". In addition to the properties above, Napier88 o ers a number of features to manipulate code. For example, in Napier88 there is no need to store programs in les as they reside in the store together with the data they manipulate. Storing data and code together means there is no danger of removing code for which data that is manipulated by it still exists, as happens with ObjectStore [39] and other object-oriented databases. No other agent system | except Tycoon [42, 43] | o ers this integration between data and code. In Napier88 it is possible to ask for the hyper-program of a procedure at run-time [34]. An hyperprogram includes the source code of the procedure and any bindings to other objects in the store including data types, data structures and other procedures. An hyper-program is just a normal object in the language and can be compiled (see below), put in the store or sent as an argument to a remote procedure. Napier88 also supports type-safe linguistic re ection. Re ection permits a program to modify or extend its own behaviour at run-time. In Napier88 re ection is achieved by allowing running programs to access the compiler, which is a standard procedure in the store [32]. Both normal programs (source code) and hyper-programs (see previous paragraph) can be compiled with the run-time compiler. (There is another compiler to create new data types dynamically.) Although procedure values are a valid representation for mobile agents in Napier88, we migrate agents as hyper-programs. Hyper-programs convey the same information but they facilitate manipulation since they o er a higher-level view (Napier88 data structure) than procedure values (byte sequences). And because hyper-programs are just normal values in the language, they o er the same properties as any other value (in particular type-safety).

Heterogeneity \Agents built on one machine [must] execute on other machines". Napier88 is compiled into an intermediate language (byte code) and then interpreted by an abstract machine [18]. Napier88 currently runs on SunSparc with SunOS 4.1, Alphas with OSF/1 and Pentium with Solaris. The Napier88 abstract machine is suciently high-level so that it can be easily ported to new machine architectures and operating systems. The Macintosh and Linux are currently being considered. Although it is possible to port Napier88 to a variety of architectures, it may not make much sense in a research language. Java itself has not been easy to port to some environments (e.g. Windows 3.1) because it assumes too many things from the O/S (e.g. threads in this case).

Performance \Agents incur space and time costs through their size, transmission time, speed of execution, etc. These costs must be kept low enough to meet the needs of applications".

The time taken to transmit a procedure between two Napier88 stores is acceptable, even though the current implementation of the language is typically 2 to 3 orders of magnitude slower than C [46]. For example, Napier88/RPC takes 13 seconds to transfer an empty Map[int,string], a data structure which includes two small procedures for integer equalTo and lessThan tests, across our departmental Ethernet. (A new Napier88 implementation has recently been completed that promises to increase performance considerably [22].) We have also shown that, for certain applications, transmitting a procedure or complex data structure pays o when compared to the time needed for the equivalent number of remote accesses required, should that procedure reside in a remote server instead. Our preferred example is a remote index at a server which can be replicated at the client to avoid remote calls every time the index is queried. Even though it may take several minutes to migrate the index, it compensates after a few dozen queries because the index is relatively stable. In addition, although performance numbers for Napier88/RPC cannot be directly comparable with other agent systems, the time taken by Napier88/RPC to migrate a small agent is typical in the agent literature. For example, Obliq takes 5 to 45 seconds to migrate a small to medium size application [10] and it takes a few seconds to migrate a small sorting function in Facile (excluding native code) [36] or a small object in Mole [8]. There are no performance gures for Tycoon/RPC at present, but a demonstration we watched suggested the same order of magnitude.

Remote Resource Access \Agents should be able to interact with locally available services and resources in their eventual execution environments".

Napier88 supports both static and dynamic binding. Dynamic binding in Napier88 is implemented with collections of bindings called environments [6, 24] in which a binding is a tuple containing a name, a type, an object and information whether the object is constant. When an agent arrives at a new program, it can test an environment for the existence of an object, then dynamically bind to that object. Because Napier88 is persistent, type-safe dynamic binding also applies to persistent objects such as databases. This is in contrast with other non-persistent agent languages where persistent resources typically reside on les or separate database systems, for which no type-safety and long-term referential integrity can be guaranteed.

Strong Typing \The agent language should use strong static typing". Although we agree that strong type-checking is a desirable feature in a programming language, type-checking cannot be always static in a persistent language because some types or even some object names are not known at compile-time [2]. This is the reason why Napier88 also supports dynamic type-checking. In addition, the type of an object can be obtained at run-time and type equivalence is structural (the type is a property of the object itself, not a compile-time decision). A type is represented by a normal value in the language that can be compared to other types for equality or transferred to other programs. These facilities immensely facilitate type-checking in a distributed persistent environment [44].

Automatic Memory Management \[Memory management is desirable because] dangling pointers are eliminated as a potential problem and memory leaks are reduced".

In Napier88, memory garbage collection during execution and disk garbage collection at the store automatically reclaim space used by objects unreachable from the persistent root. This means Napier88 does not su er from the problems experienced by unsafe languages like C or C++ that would have serious consequences in a persistent environment responsible for code and long-term data. Together, orthogonal persistence and strong type checking guarantee that referential integrity is maintained irrespective of the life time of the object and that objects are always used with their correct type. First-class procedures extend these guarantees to objects that contain code.

Stand-alone Execution \Agents should not require a [remote] connection to their originating site to execute unless the requirement arises from the application". This requirement happens to be the basis of our research. Transparent distribution | as o ered by Emerald [13, 30], DPS-algol [62] and IK [54] | may be convenient for application programmers but it also hides network latency and partial failures with terrible consequences [64]. This happens because transparency does not prevent a distributed application from performing many more remote calls than needed if application programmers had knowledge and access to distribution. Transparency also means that a distributed application may experience partial failures in any part of the application, so every single piece of code has to be written with (network) failures in mind. And because there is no centralised control in a distributed application, it is very dicult to determine the cause of the failure (let alone prevent or x it). Persistence only ampli es the problems introduced by transparent distribution [47]. Remote references and the need for remote access accumulate through time and only make the problem ever worse. Partial failures are even more problematic since the guarantee of referential integrity provided by a persistent system can no longer be maintained in a distributed environment. Finally, transitive closures are likely to be large in a type-safe persistent environment like Napier88, further amplifying the problems with remote references and partial failures. This is why Napier88/RPC was designed to help programmers build distributed persistent applications by composing autonomous programs that cooperate between them, meaning that each Napier88 program executes independently. Thus our model of distribution is not transparent and we avoid all those problems with lack of availability and scalability (see above). On the negative side, autonomy also means that local features, such as garbage collection, are not available between inter-connected stores.

Independent Compilation \The agent language should not require that all components of a distributed application using agents be compiled together".

This is already a requirement in a persistent system. A new program should be compiled against a persistent store without requiring all other programs already in the store to be re-compiled. Napier88 uses structural type equivalence and dynamic binding to link the new program at runtime safely to the existing types, data and programs in the store. The same requirement for independent compilation exists in a distributed environment in which not all programs will be always available. Again based on structural type equivalence and dynamic binding, Napier88 provides all the facilities to compile a program in one store (without access to other stores where the program will be eventually executed), migrate the program as an agent to another store, safely bind the agent to local values at the destination store and nally execute it. In addition, orthogonal persistence permits to put the agent in the store so it can survive the program execution if required by the application.

Security \An agent language should either provide its own run-time security model or be coupled with some external model that provides system security"

We agree that, although security is a separate research area from mobile agents, it is a desirable requirement for an agent language. (Knabe himself has since then changed his mind and he now believes security is an essential property for an agent language.) However, in many research agent languages security is only part of future work (e.g., Mole, Facile and Obliq). From the agent languages surveyed in this paper, only Tycoon has recently addressed security [53]. Napier88 has also not addressed this problem yet, but orthogonal persistence o ers some basic protection by its own. For example, strong type-checking guarantees that agents cannot circumvent the type system and thus prevents pointer manipulation. Particularly sensitive parts of the store (system calls, private data, etc) can always be protected by abstract data types and passwords; this is the solution already adopted for protecting low-level details in the current Napier88 implementation. A related problem to security is how to protect agents themselves from the program in which they are being executed. Although well-known strategies like encryption may be used, diculties may arise because ultimately the agent will have to be executed by the abstract machine. We speculate that a compromise, in which the agent incrementally reveals its intentions, is probably better than all-or-nothing security.

Summary In this section we have described how Napier88 and our RPC o er all the desirable

and essential properties of an agent language, except perhaps security (although some features are provided). It is interesting to note that, probably as a consequence of orthogonal persistence, the Napier88 environment is sometimes better suited for mobile agents than some agent languages themselves. Specially interesting features include: persistence for data and code, rst-class procedures, structural type equivalence and dynamic type-checking and dynamic binding. The next section explains why in our opinion persistence is an important issue for all agent languages.

2.3 Persistence and Agent Languages In his thesis, Knabe gives several examples of applications for mobile agents. The main idea behind agents is that an RPC is not exible enough because the interface provided by an RPC is xed to the set of remote procedures available at the server. By permitting to send code to the server instead of mere data, an agent system (as opposed to an RPC system) can \program the server dynamically" to extend the set of remote procedures as needed. Two of the best applications for agents are reduced loads at the server and reduced communication costs, both achieved by downloading and executing part of the program remotely. However, it is interesting to note that many of the examples given for agent applications also include migrating data or accessing databases. The example presented by Knabe himself in chapter 5 of his thesis is a collection of remote database accesses (a map, an agenda, etc). That is only natural; we have to accept that most programs downloaded to interact with the end-user need to carry some data to display, use local objects or access a remote database. All these examples suggest the need for addressing persistence in an agent context. For example, if an agent uses a local database, then migrates to another program, should the agent bring the database with it ? Should it access the database remotely ? Should it duplicate the database, and if yes, should there exist any replication protocol to keep the replicas consistent ?

Unfortunately, these questions are typically not addressed by the agent community. But if we want to build better models and systems for programming mobile agents, and if persistence is a common requirement for agents, then there can be advantages in addressing these two research areas together. As we will see in the next two sections, this integration creates a few opportunities but also poses a number of challenges to the agent and persistence communities.

3 Opportunities In this section we give examples of opportunities in the combination of persistent systems with mobile agents. These opportunities occur both ways: using persistence to build better agents, and using agents to built better distributed persistent applications.

3.1 Mobility as Persistence The basic idea behind persistence is to exchange objects automatically between the store and the program as needed by the application. Initially, objects are created in the program but they move to the store before the execution terminates, so they are available to the next program execution. In an orthogonally persistent system with a rich type system like Napier88, these objects include data (integers, reals, string, structures, vectors and so on) and code (procedures, abstract data types, etc). Many researchers have noted that mobility and persistence are intrinsically related because mobility is conceptually similar to persistence if the store is replaced by another program. The same can be observed the other way round: persistence is just mobility in which one program behaves as being the store. This argument can be found in the literature [29, 11, 26, 19, 50, 43, 9]. Figure 2 illustrates how the same algorithms can be applied to both program-store and programprogram communication. For example, the Napier88 standard library [33], for example, o ers some basic support for distribution implemented by variants of the procedures that already exist to implement persistence [50]. Both Tycoon/RPC [43] and the latest version of Napier88/RPC [45, 46] use the same approach. Persistent System

Persistent System

Program

Program

Store

Store

Fig. 2. Similarities of Persistence and Mobility The opposite is also true. The same procedures for marshaling and un-marshaling arguments to

remote procedures can be used to export objects to a le or import (previously exported) objects from a le. We give as an example the pickling procedures for Modula-3 (incorporated into Network Objects [12]) that can also be used to implement a limited form of persistence. Agent systems in a persistent environment can take advantage of these algorithms instead of using conventional languages and (re-)implementing their own migrating procedures. For example, the implementors of Mole, an agent system based on Java, have already demonstrated interest [9] in a forthcoming persistent version of Java [4]. However, this opportunity should be addressed with caution since persistence is not exactly the same as mobility. The store is guaranteed to contain all objects reachable from an object. This is not true between programs developed and executed independently. In a persistent system only the newly created or changed objects have to be put in the store. Without proper treatment of transitive closures, large parts of the program would always have to be transmitted to the other program (see section 4). This opportunity may also suggest there could be advantages to work with mobility at the same level as persistence, namely below the abstract machine level. However, it may be dicult to work at such a low-level, especially since the agent mechanism has to be translated into highlevel language constructs to be of any use to application programmers. Another problem may occur if the implementation of the agent language is continually changing, as happens with any experimental research language like Napier88.

3.2 Database Agent Language Relational database systems accept queries written in SQL, a declarative language. More recently, with the advent of client/server computing, it has become typical for a PC (the client) to send SQL requests to a UNIX machine (the server) so that the query can be executed where the database resides (see gure 3). In this sense SQL is a well-know, established database agent language, although there are not many references to SQL in the agent literature. Client

Server SQL

Program

Program

data

Relational Database

Fig. 3. Database Query with SQL SQL is a proprietary language since each database vendor o ers its own extensions to SQL. This makes dicult for a client to make requests against di erent databases. To solve this problem, Microsoft has proposed ODBC | for Open DataBase Connectivity | to o er an API for a wellde ned, stable sub-set of SQL supported by most database vendors. ODBC has become already a standard de facto. (OBDC 3.0, the next release, will go further and support the ANSI/ISO SQL

standard.) This makes SQL with an ODBC interface the heterogeneous database agent language of the commercial world. Although the objectives of most agent systems go far beyond remote database access, we propose that designers and implementors of these systems should take a closer look at existing solutions that are tested everyday in the real world. Maybe de ning a sub-set of a well-know language for writing agents is the key to success, instead of attempting to support high-level, full featured but complicated research languages. For example, the latest version of Netscape not only supports Java applets but it also supports a simpler version of the language called JavaScript. According to the Netscape home page \The JavaScript language resembles Java, but without Java's static typing and strong type checking. JavaScript supports most of Java's expression syntax and basic control ow constructs. In contrast to Java's compile-time system of classes built by declarations, JavaScript supports a run-time system based on a small number of data types representing numeric, Boolean, and string values. [...] Using JavaScript, even less-experienced developers will be able to direct responses from a variety of events, objects, and actions."

3.3 Higher-order RPC An RPC system permits to call a remote procedure in another program. Conventional RPC systems, especially commercial implementations, are usually very restrictive in the types they support as arguments to the remote procedures. For example, Sun/RPC [56] only supports a few base types and simple constructors such as structures. Even modern \object-oriented" RPC implementations based on CORBA [51] such as Java/IDL [57] do not extend this set signi cantly (most of all they add remote references). We have discussed in section 2.3 how agents have appeared as an answer to this limitation. However, there is a new brand of higher-order RPC systems that support much richer data types as arguments to remote procedures, namely procedures themselves. Sometimes these RPC systems are embedded in a distributed programming language, although in this paper we only consider systems that pass arguments explicitly by copy (see \Stand-alone Execution" in section 2.2). Examples of these higher-order RPC include remote evaluation [55] and more recently Obliq [14, 10]. In the persistent community we nd remote execution [25], Tycoon/RPC [42, 43] and our own Napier88/RPC [45, 46]. Although from a di erent starting point and with di erent objectives, many of these projects achieve the same results and share the same problems as the agent research community with systems like Facile [36] and Mole [8]. This is indeed the raison d'^etre of this paper. For example, remote execution was proposed but never implemented because of the diculties we describe in the next section.

4 Challenges Most challenges in this section are based on the fact that agents should migrate by copy, and the complexity and size of their transitive closures. Migrating objects by reference, in which only a remote reference for the object is actually sent to the target program, creates availability and scalability problems (see \Stand-alone Execution" above). Migrating by reference is even less appropriate for agent systems where autonomy between programs is one of the main requirements.

Migration by copy means that free variables that are bound to the agent have also to be copied to the destination store. The problem is what to do if these free variables reach large parts of the program. For example, most procedures in Napier88 have very large transitive closures, frequently they reach the entire store. Type-safe but non-persistent languages have a similar (if reduced) problem: even if transitive closures are limited to the address space, libraries and other local resources used by agents (such as system calls, site-speci c objects and so on) have to be dealt with properly or the agent will fail remotely. Even though most agent systems migrate agents by deep copy and thus support free variables, in our opinion the consequences of large transitive closures have not been fully understood by the agent community. For example, although strategies for marshaling and pickling simple data structures are now well understood, our experience suggests these algorithms may not scale to large, complex agents [46]. Performance is not the only problem. For example, Mole [8] implements agents as instances of a Java class. If the class version needed to execute the object remotely is not found on the destination machine, then the source machine should be able to provide the code for this class. It is not clear what happens if: the agent refers to other (large) objects such as a database; the class of the object requires other code to execute (e.g., a local library, as opposed to the standard Java libraries); or the migrating object refers to other objects for which the class is no longer available (e.g., the le was moved or deleted). Without addressing these issues, only the simplest objects can be sent to other programs.

4.1 Reducing the Transitive Closure A well-know approach to reduce the transitive closure of an object is to ask application programmers to make a distinction at compile-time between those objects that migrate by copy and those that migrate by reference only (i.e., that are not actually sent). For example, large objects or sitespeci c objects can be accessed remotely by de ning an interface written in IDL as in CORBA [51] or in a more exible manner by specialising the arguments of the remote procedures to transmit only part of the object graph [40]. On-demand, shallow, partial, or lazy object migration can also be used automatically by the system at run-time as in Emerald [13, 30], DPS-algol [62], HiRPC [31, 38] or GUM [60], with or without hints by application programmers. However, all these solutions are just clever optimisations that trade-o copying by references, introducing the potential for partial failures with unpredictable consequences. Another approach to reduce the transitive closure which does not create remote references, proposed independently by several researchers, is simply not to migrate at all objects that already exist in the target program. For example, Facile proposes ubiquitous values [35, 36] for which equivalent implementations of the value exist in both the originating and destination sites. Tycoon/RPC [42, 43] lets programmers register modules as ubiquitous resources (such as parts of standard libraries). Step 4 of the migration command in Obliq says that \links to the local runtime are explicitly removed" [10]. Octopus [27, 28] is another proposal to allow application programmers themselves to manipulate bindings in persistent objects. As part of our work with Napier88 we have designed and implemented a mechanism called migration by substitution [47, 46] in which only a surrogate identifying the object migrates to the target program. In the implementation, the surrogate is just a name that has been previously agreed between the source and target programs (see next paragraph). On arrival at the target program, the name is replaced by an equivalent object of the same type. Standard utilities such

as the Napier88 Standard Library [33] and Glasgow Libraries [63] always migrate by substitution in our experiments. Our model of migration by substitution is similar to other approaches. However, in our mechanism equivalent objects are de ned dynamically (i.e., new objects can be added or existing ones removed at run-time), by name (i.e., we do not require equivalent objects to have the same value) and the mechanism is still strongly type-safe (i.e., equivalent objects are type-checked between the source and target programs). Other mechanisms fail to provide one or more of these features.

4.2 Sharing Objects Between Stores Although most agents would probably not require any remote connection to the originating program, some agents will require this facility. For example, an agent sent to a server program to execute a computation remotely may need further data only if some assumption at the destination is true; the agent may require more code (e.g., a word processor may require a spell checker); or the agent may need to access some changing data such as a stock value. But remote access is itself a solution to a more general problem: how to share objects between other objects that reside in di erent programs. There are basically two approaches to solve the sharing problem in a distributed system: one copy (by remote access, see previous paragraph) or many copies (using some sort of replication protocol) [23]. Below we describe each of these approaches in turn. Figure 4 illustrates the one-copy approach. If both A and B refers to C, then if A migrates to another program, a remote reference to C can be created and the new object A' only carries this remote reference with it. (A and A' are two distinct objects because each has its own local OID.) Remote references are convenient because they provide a simple programming model, but remote access is slow, typically 4 to 5 orders of magnitude slower than a local reference, and unreliable, because it may not work due to network congestion, partition, failures, etc. Persistent System

Persistent System migration

A

A’

B remote reference C

Fig. 4. Inter-store Object Sharing with One Copy A better approach, especially for mobile agents in a persistent environment, is to duplicate the shared object remotely (see gure 5). In this approach C also migrates to the destination program together with A. The problem now is to maintain the replicas consistent when they are updated. Strict replication protocols that maintain the replicas always consistent can be used, but they require remote references and thus su er from similar problems as the one-copy approach.

Persistent System

Persistent System

A

migration

A’

B

C

replication protocol

C’

Fig.5. Inter-store Object Sharing with Many Copies Obliq is a truly distributed language and permits to share objects remotely using the one-copy approach. A similar behaviour can be achieved in Tycoon/RPC by calling remote procedures (network objects are promised for the future). In Facile there are no high-level provisions for sharing at present, but a data type called channel can be used to access an object remotely (the application has to implement its own protocol, marshaling, etc). In addition, all these languages also permit to duplicate objects remotely, although no help is provided for maintaining replicas consistent. In order to deal with distributed object sharing we have proposed and implemented a compromise between the one-copy and many-copies approach called persistent spaces [46]. Using persistent spaces, a publisher releases objects that can be later fetched by any number of subscribers. By putting them in a persistent space, A and B can be updated at any time but the replicas A' and B' are synchronised explicitly by each subscriber. This synchronisation incurs the same costs as the many-copies approach but we allow the application programmer to choose when to pay the price, not every time A or B are updated. Each persistent space thus groups related objects (in this example A and B) that share some object(s) in the publisher and will share the same object(s) in the subscriber. An example of a persistent space is a group of procedures and data representing an agent. In a persistent space marshaling is made at publishing time. This means persistent spaces have many other advantages: they permit to check locally if a group of objects can be exported; they amortise marshaling over a number of subscriptions; they return the packet size (containing the marshaled objects) before transmission actually occurs; and packets can be transmitted at any convenient time (e.g., at 4am) and using a wide range of media (e.g., by e-mail, le transfer or even by disk).

4.3 Maintaining Sharing Semantics Another problem with free variables occurs when objects that locally share another object(s) migrate to the target program. (The same happens if the same object migrates more than once). Figure 6 shows what happens in a typical RPC system when A migrates, then B also migrates but in another remote call. The duplication of C in the target program produces semantic decay because A' and B' do not o er the same behaviour as A and B; transmission and space wastage because C is transfered twice and stored twice; and state ambiguity if many updates or separate

program executions occur between the call that sends A and the one that sends B. A combinatorial explosion occurs if C is large and/or shared by many other objects ! Persistent

System

A

Persistent first migration

System

A’

B

C

B

second migration

C’

C’’

Fig. 6. Lost of Object Sharing in Successive Migrations Persistent spaces can also be used as a rst step towards solving this problem because within persistent spaces the common sub-structure sharing is maintained. Thus if A and B belong to the same persistent space, only one copy of C will be created in the target program. Persistent spaces also keep only one copy of C' if A and B migrate separately because the common sub-structure in a persistent space is maintained between successive transmissions. (However, separate spaces will have separate copies of sub-structures. The application programmer can then opt for maintaining or not common sub-structures.

4.4 Large and/or Complex Objects Even after applying migration by substitution and using persistent spaces, the number of migrating objects may still be very large. For example, in one of our experiments we migrated a map representing an index containing 3,389 entries. The total number of objects amounted to 10,486 and the packet size to approximately 500 KB. The index took 37 minutes to be transmitted and rebuilt at the destination program. On the other hand, we have measured that just sending a byte array with 500 KB from one program to another program across our departmental Ethernet takes only 3{4 seconds, including the time to open the socket connection. The conclusion we can take is that the time to pack and unpack is clearly dominant for large and/or complex objects. More worryingly, migration time in Napier88/RPC increases quadratically to the number of objects being migrated as a result of the packing algorithm. Finally, because these operations are CPU intensive, signi cant performance improvements are also limited by the implementation of the language itself. For each object, the marshaling algorithm has to check whether this object has already been packed to deal with shared and cyclic data structures [29]. In order to implement this check, a data structure is used that maintains a reference to all packed objects. Ideally, this data structure would permit fast access by reference, such as a b-tree or an hash table. But in a threaded persistent system with garbage collection references may change at any time from a volatile representation (memory pointer) to a persistent representation (object identi er). In non-persistent non-safe programming language, pointers are just xed memory addresses and

the fast access methods can be used based on them. In a persistent system, however, we have no access to the reference implementation and a linear search comparing reference by reference is very dicult to avoid. An obvious solution to this problem would be to have a persistent unique OID for each object and access objects by OID and not by reference. However, we have measured that most objects in the store are small (16 bytes or less). An OID with 8 bytes would represent an unacceptable cost in terms of both space and CPU usage. Although we have been assured by Knabe [37] and Mathiske [41] that both Facile and Tycoon (respectively) perform \fast" marshaling, we have no knowledge about published measurements on migrating such large data structures. These are needed to con rm if our performance problems also appear in other systems or not. If Facile and Tycoon also show quadratic behaviour, this means that even the fastest migration algorithm would become of no use after a certain scale.

4.5 Mobility Orthogonal to Type Until now we have assumed that certain objects can migrate whereas others cannot. But why should only special objects in the language be agents ? Why is not possible to migrate objects of any type ? Does it make sense ? Can it be implemented ? These questions are interesting because most agent languages identify an agent at compilationtime, thus restricting the set of objects which can later migrate. For example, Facile identi es \possible transmissible functions" by relying on the programmer to annotate these before compilation, and only these functions are potential agents. In Obliq, agents are special procedures that contain a suitcase and no other free variables (except if belonging to the user interface, which do not truly migrate because the links to them are cut by the migration command). Only applets can migrate in Java, not an arbitrary Java application. On the other hand, one of the requirements for orthogonal persistent systems is \all objects in the language have the right to persist". So at least for a persistent programmer it makes perfect sense that \all objects in the language have the right to migrate". Migration orthogonal to type is specially important because non-orthogonal migration will eventually su er from the same problems as non-orthogonal persistence. What if the programmer decides later to migrate an object that is non-migratable ? What if a migratable object refers to a non-migratable object ? Migration orthogonal to type is also possible to implement | in principle, apart from the challenges described in this section | as there are no such restrictions on mobile types and objects in both Tycoon/RPC and Napier88/RPC. (Instances of abstract data types pose special problems that we are still investigating [20]. This is the reason why threads, implemented as instances of the abstract data type Thread in Napier88, cannot migrate in Napier88/RPC.) We propose that any procedure in any program | or indeed any object which refers to an object that contains code | is potentially a mobile agent. This generality is convenient but introduces new problems. For example, because the transitive closure of a persistent object is typically large, there may be cases in which the entire transitive closure cannot migrate. These include semantic restrictions (e.g., there is a single persistent root in each store so it is meaningless to migrate the root to another store) or engineering limitations (it may be very dicult or simply take too much time). According to Knabe, the reason for restricting the set of transmissible values is \performance, performance, performance" [37]. In an agent language based on native (machine) code such as

Facile, generating machine-independent byte code can double the space needed for programs. However, as Knabe also notes, run-time (also called just-in-time) compilation can be used to generate machine code on demand. Byte code can also be used directly, as in Java and Napier88. Knabe's thesis has achieved some interesting results, but more research is needed to assert the trade-o s between di erent code representations (compilation on-demand, native code, byte code, all of them, etc) when compared to space requirements and transmission time.

4.6 Failure Model for Migration Unlike static analysis of code or compile-time rules to decide if an object can migrate, the decision to migrate or not can instead be delayed until migration time. When migration cannot be achieved, the attempt should raise an exception. The exception should ideally explain | in terms understandable to application programmers | why the migration could not succeed. For example, the program can pass information about the failure to the end user or may try to migrate another (e.g., smaller or simpler) agent. A model based on a single exception as in Facile [37] is not enough because it does not convey enough information to enable the program to take decisions. Instead, a sophisticated failure model is needed that can explain why a migration did not succeed. Examples of these reasons are: references to the outside world that only make sense locally (e.g., descriptors to open les); values with types that do not exist remotely (so they cannot be used); values that create implementation problems for transmission (e.g., instances of abstract data types); and semantic problems (such as private data or attempting to transmit the persistent root in Napier88). Persistent spaces may help to provide a failure model because marshaling (the tricky part of migrating an agent) occurs locally in the publisher program. This simpli es the detection and treatment of some kind of errors, but a general approach to deal with all failures which may occur during migration is still needed.

4.7 Standard Agent Language Each agent language and system uses its own model and algorithms to migrate procedures and other objects between programs. This resembles the rst days of RPC, when each RPC system was designed for a particular language and marshaled arguments in a manner di erent from any other RPC system. Eventually CORBA was proposed to allow programs written in di erent languages to exchange data between them, and a number of CORBA implementations have since then been built. Now the latest CORBA speci cation [51] even supports inter-operability between di erent CORBA implementations via standard transport protocol and data format. (Note that this is not a technical challenge; the main challenge is to convince the world to accept \your" standard.) Although probably not a technical challenge, the following questions still make an interesting topic for the agent community. Does it make sense to design and build an agent system independent of the actual programming languages in which the source and target programs are written ? If yes, what kind of agent language would that be ? Would it be based on an existing language or be a common sub-set of the most popular agent languages ? In section 3.2 we have presented ODBC, a standard interface to process database queries against relational databases from a number of vendors. But ODBC 3.0 o ers many facilities beyond just

a standard SQL interface, for example, it permits to check if the remote database is alive, o ers monitoring tools, etc. Other extensions to ODBC have been made to specify rules and replicate tables across di erent databases. Some ODBC products support inter-operability with the World Wide Web. ODBC has also an advantage compared to most agent languages: it is already prepared to access databases, a typical agent application. Is ODBC quietly becoming a standard de facto for a database agent language ?

5 Summary and Future Work In the last 3 years we have been working with persistence and distribution. During this time we have built a higher-order RPC mechanism that permits to exchange procedures and other complex data structures between autonomous persistent programs. It was not by chance that we have achieved many of the same results | and encountered many of the same diculties | as researchers working with mobile agents. It only means that agents are in fact complex data structures migrating from one program to another program. Our main objective with this paper is to bring into the agents research community our experience with persistent systems, Napier88, and our research work. At the same time we want to understand better the speci c problems of mobile agents. In order to achieve this objective, the paper has 1) introduced persistence, Napier88, our own research with Napier88/RPC, and their potential suitability as an agent system; 2) presented the opportunities that exist in the combination of persistent systems and mobile agents; and 3) discussed a number of problems that we have encountered in a persistent environment. These challenges will become more important as mobile agents start to play an ever greater role in real-world distributed applications. This is because many of the practical uses for mobile agents access databases or carry other objects with them, including more code. In order to deal with these problems, we have proposed migration by substitution and persistent spaces. Migration by substitution o ers a exible mechanism to reduce the transitive closure of an agent by cutting links to objects that also exist in the destination store. Persistent spaces help with sharing objects between stores and maintaining sharing semantics, even between transmissions. Remaining challenges for which we have not found yet a satisfactory solution are: marshaling algorithms that scale for large data structures; ecient migration orthogonal to type; a simple but comprehensive failure model; and an answer to the need and form of a standard agent language. The research area which addresses mobile agents is still in its infancy. This is suggested by the di erent terminology available in the literature (e.g., mobile agents and network agents) and many example applications inherited from other research areas. The next few years will probably see dramatic improvements in the agent semantics [15] and technology that are not clearly understood today. Security is an example of a property for agent languages that will have to be addressed properly in the future, as security seems to be a requirement for real-world agent applications. Other problems will no doubt be revealed once we have solved these and attempt more complicated applications. Java, now well positioned to take the lead in mobile computing for some years to come, is de nitely a language that deserves attention. However, Java is only an intermediate step towards long-lived, large-scale distributed applications. This is because Java separates mobile code from mobile data (applets do not include objects) and does not address persistence properly (e.g., a recent proposal for database access in Java o ers an SQL interface [59]).

In the meantime other commercial systems will no doubt be proposed. For example, Visual Basic is also being positioned as a \network language" with support from Microsoft, and the existing 2 million users of Visual Basic will at the very least look Java with suspicion. It will also be interesting to see the reaction of other large computer companies such as IBM (said to have an in-house network language) and Digital (with Obliq, a truly distributed language that seamlessly migrates data and code). Another promising alternative to Java is PJava, or Persistent Java [4]. PJava has been designed and is currently being implemented in the University of Glasgow (Scotland) as an orthogonally persistent version of Java. The PJava project is partially supported by Sun. It has been recognised that PJava will lead to interesting combinations of persistence and distribution. Will PJava be the ultimate agent language ?

Acknowledgements The authors would like to acknowledge Fritz Knabe and Bernd Mathiske who read previous versions of this paper and made innumerous comments. Many other people have contributed to this paper, specially Andrew Black, Joachim Baumann, Peter Dickman, and Peter Larsson. The research environment in Glasgow has been partially supported by projects FIDE2 and IMIS, and is now supported by projects DRASTIC, PJava and ZEST. Miguel Mira da Silva is partly supported by JNICT.

References 1. M.P. Atkinson, P.J. Bailey, K.J. Chisholm, W.P. Cockshott, and R. Morrison. An approach to persistent programming. The Computer Journal, 26(4):360{365, November 1983. 2. M.P. Atkinson, O.P. Buneman, and R. Morrison. Binding and type checking in database programming languages. The Computer Journal, 31(2):99{109, April 1988. 3. M.P. Atkinson, K.J. Chisholm, and W.P. Cockshott. PS-algol: An algol with a persistent heap. ACM SIGPLAN Notices, 17(7):24{31, July 1982. 4. M.P. Atkinson, M. Jordan, L. Daynes, and S. Spence. Design issues for persistent Java: A type-safe, object-oriented, orthogonally persistent system. In Proceedings of the Seventh International Workshop on Persistent Object Systems (Cape May, New Jersey, USA, May 29-31, 1996), 1996. Accepted for publication. 5. M.P. Atkinson and R. Morrison. Procedures as persistent data objects. ACM Transactions on Programming Languages and Systems, 4(7):539{559, October 1985. 6. M.P. Atkinson and R. Morrison. Polymorphic names and iterations. In F. Bancilhon and O.P. Buneman, editors, Advances in Database Programming Languages, ACM Press, Frontier Series, pages 241{ 256. Addison-Wesley Publishing Company and ACM Press, 1990. Edited Proceedings of the Workshop on Database Programming Languages (Rosco , Brittany, France, September 1987). 7. M.P. Atkinson and R. Morrison. Orthogonal persistent object systems. VLDB Journal, 4(3):319{401, 1995. 8. J. Baumann. Mole: The project. Institute for Parallel and Distributed High Performance Systems, University of Stuttgart, 1996. Collection of slides. 9. J. Baumann. Private communication, 1996. 10. K. Bharat and L. Cardelli. Migratory applications. In Proceedings of ACM Symposium on User Interface Software and Technology '95 (Pittsburgh, PA, Nov 1995), 1995. 11. A. Birrel, M. Jones, and E. Wobber. A simple and ecient implementation for small databases. In Proceedings of the Eleventh ACM Symposium on Operating Systems Principles, November 1987. 12. A. Birrell, G. Nelson, S. Owicki, and E. Wobber. Network objects. In Proceedings of the 14th ACM Symposium on Operating Systems Principles, pages 217{230, December 1993.

13. A. Black, N. Hutchinson, E. Jul, H. Levy, and L. Carter. Distribution and abstract types in Emerald. IEEE Transactions on Software Engineering, SE-13(1):65{76, January 1987. 14. L. Cardelli. A language with distributed scope. Computing Systems, 8(1):27{59, January 1995. A preliminary version appeared in Proceedings of the 22nd ACM Symposium on Principles of Programming Languages. 15. L. Cardelli. Mobile computation, 1995. Position Paper. 16. R.C.H. Connor. Types and Polymorphism in Persistent Programming Systems. PhD thesis, University of St Andrews, 1991. 17. R.C.H. Connor, D. Balasubramaniam, and R. Morrison. Investigating extension polymorphism. In Proceedings of the Fifth International Workshop on Database Programming Languages (Gubbio, Umbria, Italy, 6th-8th September 1995). Springer-Verlag, 1996. Accepted for publication. 18. R.C.H. Connor, A.L. Brown, R. Carrick, A. Dearle, and R. Morrison. The persistent abstract machine. In J. Rosenberg and D.M. Koch, editors, Persistent Object Systems, pages 353{366. Springer-Verlag, 1990. 19. D.H. Craft. A study of pickling. Journal of Object-Oriented Programming, January 1993. 20. Q. Cutts and M. Mira da Silva. Building type-safe distributed applications using existential types. Abstract accepted to the Software Technology Track of the 30th Hawaii International Conference on System Sciences (Maui, Hawaii, USA, January 7-10, 1997), March 1996. 21. Q.I. Cutts. Delivering the Bene ts of Persistence to System Construction and Execution. PhD thesis, University of St Andrews, 1993. 22. Q.I. Cutts, R.C.H. Connor, and R. Morrison. The PamCase machine. In M.P. Atkinson, editor, Fully Integrated Data Environments, chapter 2.1.3. Springer-Verlag, 1995. 23. J. Daniels and S. Cook. Strategies for sharing objects in distributed systems. Journal of ObjectOriented Programming, January 1993. 24. A. Dearle. Environments: A exible binding mechanism to support system evolution. In B.H. Shriver, editor, Proceedings of the Twenty-Second Annual Hawaii International Conference on System Sciences, Volume II Software Track (January 1989), pages 46{45, 1989. 25. A. Dearle, J. Rosenberg, and F. Vaughan. A remote execution mechanism for distributed homogeneous stable stores. In P. Kanellakis and J.W. Schmidt, editors, Database Programming Languages: Bulk Types and Persistent Data. Morgan Kaufmann Publishers, 1991. Proceedings of the Third International Workshop on Database Programming Languages (Nafplion, Greece, 27th{30th August 1991). 26. G.N. Dixon, S.K. Shrivastava, and G.D. Parrington. Managing persistent objects in Arjuna: A system for reliable distributed computing. In R. Carrick and R.L. Cooper, editors, Proceedings of the Second International Workshop on Persistent Object Systems: Their Design, Implementation and Use, pages 246{265. Universities of Glasgow and St Andrews, 1987. 27. A. Farkas and A. Dearle. Octopus: A re ective mechanism for object manipulation. In C. Beeri, A. Ohori, and D.E. Shasha, editors, Proceedings of the Fourth International Workshop on Database Programming Languages: Object Models and Languages (Manhattan, New York City, USA, 30th August{1st September 1993). Springer-Verlag in collaboration with the British Computer Society, 1993. 28. A. Farkas and A. Dearle. The Octopus model and its implementation. Australian Computer Science Communications, 16(1), 1994. 29. M. Herlihy and B. Liskov. A value transmission method for abstract data types. ACM Transactions on Programming Languages and Systems, 4(4):527{551, October 1982. 30. E. Jul, H. Levy, N. Hutchinson, and A. Black. Fine-grained mobility in the Emerald system. ACM Transactions on Computer Systems, 6(1), February 1988. 31. K. Kato, A. Ohori, T. Murakami, and T. Masuda. Distributed C language based on a higher-order RPC technique. Computer Software, 9(3), 1993. (in Japanese, also published in English by Iwanamim Shoten, Publishers and Academic Press, Inc.). 32. G.N.C. Kirby. Re ection and Hyper-Programming in Persistent Programming Systems. PhD thesis, University of St Andrews, 1993. 33. G.N.C. Kirby, A.L. Brown, R.C.H. Connor, Q.I. Cutts, A. Dearle, V.S. Moore, R. Morrison, and D.S. Munro. The Napier88 standard library reference manual version 2.2. Technical Report FIDE/94/105, ESPRIT Basic Research Action, Project Number 6309 | FIDE2 , 1994. 34. G.N.C. Kirby, R.C.H. Connor, Q.I. Cutts, R. Morrison, A. Dearle, and A.M. Farkas. Persistent hyperprograms. In A. Albano and R. Morrison, editors, Proceedings of the Fifth International Workshop on

35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59.

Persistent Object Systems (San Miniato, Italy, 1st{4th September 1992), Workshops in Computing, pages 86{106. Springer-Verlag in collaboration with the British Computer Society, 1992. F. Knabe. Function transmission for a distributed higher-order language. Extended Abstract, November 1994. F. Knabe. Language Support for Mobile Agents. PhD thesis, Carnegie Mellon University, Pittsburgh, PA 15213, USA, December 1995. F. Knabe. Private communication, 1996. K. Kono, K. Kato, and T. Masuda. Smart remote procedure calls: Transparent treatment of remote pointers. In Proceedings of the 14th International Conference on Distributed Computing Systems (Poznan, Poland, June 21{24, 1994). IEEE Computer Society Press, 1994. C. Lamb, G. Landis, J. Orenstein, and D. Weinreb. ObjectStore. Communications of the ACM, 34(10):51{63, October 1991. C. Lopes. Adaptive parameter passing. In Proceedings of the 2nd International Symposium on Object Technologies for Advanced Software (Kanazawa, Japan, Mar. 11-15, 1996), volume 1049. SpringerVerlag, 1996. B. Mathiske. Private communication, 1996. B. Mathiske, F. Matthes, and J.W. Schmidt. On migrating threads. In Proceedings of the Second International Workshop on Next Generation Information Technologies and Systems (Naharia, Israel, June 1995), 1995. B. Mathiske, F. Matthes, and J.W. Schmidt. Scaling database languages to higher-order distributed programming. In Proceedings of the Fifth International Workshop on Database Programming Languages (Gubbio, Umbria, Italy, 6th-8th September 1995). Springer-Verlag, 1996. Accepted for publication. M. Mira da Silva. Automating type-safe RPC. In O.A. Bukhres, M.T. O zsu, and M.C. Shan, editors, Proceedings of The Fifth International Workshop on Research Issues on Data Engineering: Distributed Object Management (Taipei, Taiwan, 6th{7th March 1995), pages 100{107. IEEE Computer Society Press, 1995. M. Mira da Silva. Programmer's manual to Napier88/RPC 2.2. Technical Report FIDE/95/133, ESPRIT Basic Research Action, Project Number 6309 | FIDE2 , 1995. M. Mira da Silva and M.P. Atkinson. Higher-order distributed computation over autonomous persistent stores. In Proceedings of the Seventh International Workshop on Persistent Object Systems (Cape May, New Jersey, USA, May 29-31, 1996), 1996. Accepted for publication. M. Mira da Silva, M.P. Atkinson, and A. Black. Semantics for parameter passing in a type-complete persistent RPC. In Proceedings of the 16th International Conference on Distributed Computing Systems (Hong-Kong, May, 1996), 1996. Accepted for publication. R. Morrison, A.L. Brown, R.C.H. Connor, Q.I. Cutts, A. Dearle, G.N.C. Kirby, and D.S. Munro. The Napier88 reference manual release 2.0. Technical Report FIDE/94/104, ESPRIT Basic Research Action, Project Number 6309 | FIDE2 , 1994. R. Morrison, A.L. Brown, R.C.H. Connor, and A. Dearle. The Napier88 reference manual. Technical Report PPRR-77-89, Universities of Glasgow and St Andrews, 1989. D.S. Munro. On the Integration of Concurrency, Distribution and Persistence. PhD thesis, University of St Andrews, 1993. OMG | Object Management Group, Inc. The Common Object Request Broker: Architecture and Speci cation (CORBA), 1995. OSF | Open Software Foundation. Java Mobile Code: A White Paper, 1996. A. Rudlo , F. Matthes, and J.W. Schmidt. Security as an add-on quality in persistent object systems. In Second International East/West Database Workshop, Klagenfurt, Austria, Workshops in Computing, pages 90{108. Springer-Verlag, 1995. P. Sousa, A. Zuquete, N. Neves, and J.A. Marques. Orthogonal persistence in a heterogeneous distributed object-oriented environment. The Computer Journal, 37(4), September 1994. J. W. Stamos and D. K. Gi ord. Remote evaluation. ACM Transactions on Programming Languages and Systems, 4(12):537{565, October 1990. Sun Microsystems. RPC Programming Guide, 1993. Sun Microsystems. Java IDL, March 1996. Early Access Release (alpha1). Sun Microsystems. Java Remote Method Invocation, March 1996. Early Access Release (alpha1). Sun Microsystems. JDBC: A Java SQL API, March 1996. Version 0.50.

60. P. Trinder, K. Hammond, J. Mattson, A. Partridge, and S. Peyton Jones. GUM: A portable parallel implementation of Haskell. In Proceedings of the 1996 Conference on Programming Language Design and Implementation (Philadelphia, USA, 1996), 1996. 61. Arthur van Ho . Java and Internet programming. Dr. Dobb's Journal, August 1995. 62. F. Wai. Distributed Concurrent Persistent Programming Languages: An Experimental Design and Implementation. PhD thesis, University of Glasgow, April 1988. 63. C.A. Waite, R.C. Welland, T. Printezis, A. Pirmohamed, P. Philbrow, G. Montgomery, M. Mira da Silva, S.D. Macneill, D. Lavery, C. Hertzig, A. Froggatt, R.L. Cooper, and M.P. Atkinson. Glasgow libraries for orthogonally persistent systems | philosophy, organisation and contents. Technical Report FIDE/95/132, ESPRIT Basic Research Action, Project Number 6309 | FIDE2 , 1995. 64. J. Waldo, G. Wyant, A. Wollrath, and S. Kendall. A note on distributed computing. Technical Report TR-94-29, Sun Microsystems Laboratories, 1994.

This article was processed using the LATEX macro package with LLNCS style

Suggest Documents