Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > by-pkgid > 2fc07611b08d4a735fd34d5eb60d8e16 > files > 2050

ciao-1.10p8-3mdv2010.0.i586.rpm

<HTML>
<HEAD>
<!-- Created by texi2html 1.56k + clip patches and <A href="http://www.clip.dia.fi.upm.es/Software">lpdoc</A> from ciao.texi on 28 January 2007 -->

<LINK rel="stylesheet" href="ciao.css" type="text/css">
<TITLE>The Ciao Prolog System               - Active modules (high-level distributed execution)</TITLE>
</HEAD>
<BODY> 
Go to the <A HREF="ciao_1.html">first</A>, <A HREF="ciao_107.html">previous</A>, <A HREF="ciao_109.html">next</A>, <A HREF="ciao_241.html">last</A> section, <A HREF="ciao_toc.html">table of contents</A>.
<P><HR><P>


<H1><A NAME="SEC446" HREF="ciao_toc.html#TOC446">Active modules (high-level distributed execution)</A></H1>
<P>
<A NAME="IDX5432"></A>


<P>
<STRONG>Author(s):</STRONG> Manuel Hermenegildo, Daniel Cabeza.


<P>
<STRONG>Version:</STRONG> 1.10#7 (2006/4/26, 19:22:13 CEST)


<P>
<STRONG>Version of last change:</STRONG> 1.9#2 (2002/5/23, 17:48:34 CEST)


<P>
 


<P>
Active modules [CH95] provide a high-level model of 
<A NAME="IDX5433"></A>
inter-process communication and 
<A NAME="IDX5434"></A>
distributed execution (note that this is also possible using Ciao's communication and concurrency primitives, such as sockets, concurrent predicates, etc., but at a lower level of abstraction). An 
<A NAME="IDX5435"></A>
<A NAME="IDX5436"></A>
<EM>active module</EM> (or an 
<A NAME="IDX5437"></A>
<A NAME="IDX5438"></A>
<EM>active object</EM>) is an ordinary module to which computational resources are attached, and which resides at a given location on the network. Compiling an active module produces an executable which, when running, acts as a <EM>server</EM> for a number of predicates: the predicates exported by the module. Predicates exported by an active module can be accessed by a program on the network by simply "using" the module, which then imports such "remote predicates." The process of "using" an active module does not involve transferring any code, but rather setting up things so that calls in the module using the active module are executed as remote procedure calls to the active module. This occurs in the same way independently of whether the active module and the using module are in the same machine or in different machines across the network. 


<P>
Except for having to compile it in a special way (see below), an active module is identical from the programmer point of view to an ordinary module. A program using an active module imports it and uses it in the same way as any other module, except that it uses "
<A NAME="IDX5439"></A>
<CODE>use_active_module</CODE>" rather than "
<A NAME="IDX5440"></A>
<CODE>use_module</CODE>" (see below). Also, an active module has an address (network address) which must be known in order to use it. In order to use an active module it is necessary to know its address: different "protocols" are provided for this purpose (see below). 


<P>
<A NAME="DOCF3" HREF="ciao_foot.html#FOOT3">(3)</A> 


<P>
From the implementation point of view, active modules are essentially daemons: executables which are started as independent processes at the operating system level. Communication with active modules is implemented using sockets (thus, the address of an active module is an IP socket address in a particular machine). Requests to execute goals in the module are sent through the socket by remote programs. When such a request arrives, the process running the active module takes it and executes it, returning through the socket the computed answers. These results are then taken and used by the remote processes. Backtracking over such remote calls works as usual and transparently. The only limitation (this may change in the future, but it is currently done for efficiency reasons) is that all alternative answers are precomputed (and cached) upon the first call to an active module and thus <EM>an active module should not export a predicate which has an infinite number of answers</EM>. 


<P>
The first thing to do is to select a method whereby the client(s) (the module(s) that will use the active module) can find out in which machine/port (IP address/socket number) the server (i.e., the active module) will be listening once started, i.e., a "protocol" to communicate with the active module. The easiest way to do this is to make use of the redezvous methods which are provided in the Ciao distribution in the <CODE>library/actmods</CODE> directory; currently, <CODE>tmpbased...</CODE>, <CODE>filebased...</CODE>, and <CODE>webbased...</CODE>. 


<P>
The first one is based on saving the IP address and socket number of the server in a file in a predefined directory (generally <CODE>/tmp</CODE>, but this can be changed by changing <CODE>tmpbased_common.pl</CODE>). 


<P>
The second one is similar but saves the info in the directory in which the server is started (as <EM>&#60;module_name&#62;</EM><CODE>.addr</CODE>), or in the directory that a <CODE>.addr</CODE> file, if it exists, specifies. The clients must be started in the same directory (or have access to a file <CODE>.addr</CODE> specifying the same directory). However, they can be started in different machines, provided this directory is shared (e.g., by NFS or Samba), or the file can be moved to an appropriate directory on a different machine --provided the full path is the same. 


<P>
The third one is based on a 
<A NAME="IDX5441"></A>
name server for active modules. When an active module is started, it communicates its address to the name server. When the client of the active module wants to communicate with it, it asks the name server the active module address. This is all done transparently to the user. The name server must be running when the active module is started (and, of course, when the application using it is executed). The location of the name server for an application must be specified in an application file named <CODE>webbased_common.pl</CODE> (see below). 


<P>
These rendezvous methods are encoded in two modules: a first one, called <CODE>...publish.pl</CODE>, is used by the server to publish its info. The second one, called <CODE>...locate.pl</CODE>, is used by the client(s) to locate the server info. For efficiency, the client methods maintain a cache of addresses, so that the server information only needs to be read from the file system the first time the active module is accessed. 


<P>
Active modules are compiled using the <CODE>-a</CODE> option of the Ciao compiler (this can also be done from the interactive top-level shell using 
<A NAME="IDX5442"></A>
<CODE>make_actmod/2</CODE>). For example, issuing the following command: 



<PRE>
  ciaoc -a 'actmods/filebased_publish' simple_server
</PRE>

<P>
compiles the simple server example that comes with the distribution (in the <CODE>actmods/example</CODE> directory). The <CODE>simple_client_with_main</CODE> example (in the same directory) can be compiled as usual: 



<PRE>
  ciaoc simple_client_with_main
</PRE>

<P>
Note that the client uses the <CODE>actmods</CODE> package, specifies the rendezvous method by importing <CODE>library('actmods/filebased_locate')</CODE>, and explicitely imports the "remote" predicates (<EM>implicit imports will not work</EM>). Each module using the <CODE>actmods</CODE> package <EM>should only use one of the rendezvous methods</EM>. 


<P>
Now, if the server is running (e.g., <CODE>simple_server &#38;</CODE> in Un*x or double-clicking on it in Win32) when the client is executed it will connect with the server to access the predicate(s) that it imports from it. 


<P>
A simpler even client 
<A NAME="IDX5443"></A>
<CODE>simple_client.pl</CODE> can be loaded into the top level and its predicates called as usual (and they will connect with the server if it is running). 



<UL>
<LI><A HREF="ciao_108.html#SEC447">Active module name servers</A>
<LI><A HREF="ciao_108.html#SEC448">Active modules as agents</A>
</UL>



<H3><A NAME="SEC447" HREF="ciao_toc.html#TOC447">Active module name servers</A></H3>

<P>
An application using a name server for active modules must have a file named <CODE>webbased_common.pl</CODE> that specifies where the name server resides. It must have the <CODE>URL</CODE> and the path which corresponds to that <CODE>URL</CODE> in the file system of the server machine (the one that hosts the <CODE>URL</CODE>) of the file that will hold the name server address. 


<P>
The current distribution provides a file <CODE>webbased_common.pl</CODE> that can be used (after proper setting of its contents) for a server of active modules for a whole installation. Alternatively, particular servers for each application can be set up (see below). 


<P>
The current distribution also provides a module that can be used as name server by any application. It is in file 
<A NAME="IDX5444"></A>
<CODE>examples/webbased_server/webbased_server.pl</CODE>. 


<P>
To set up a name server edit <CODE>webbased_common.pl</CODE> to change its contents appropriately as described above (<CODE>URL</CODE> and corresponding complete file path). Then recompile this library module: 

<PRE>
    ciaoc -c webbased_common
</PRE>

<P>
The name server has to be compiled as an active module itself: 

<PRE>
    ciaoc -a actmods/webserver_publish webbased_server
</PRE>

<P>
It has to be started in the server machine before the application and its active modules are compiled. 


<P>
Alternatively, you can copy <CODE>webbased_common.pl</CODE> and use it to set up name servers for particular applications. Currently, this is a bit complicated. You have to ensure that the name server, the application program, and all its active modules are compiled and executed with the same <CODE>webbased_common.pl</CODE> module. One way to do this is to create a subdirectory <CODE>actmods</CODE> under the directory of your application, copy <CODE>webbased_common.pl</CODE> to it, modify it, and then compile the name server, the application program, and its active modules using a library path that guarantees that your <CODE>actmods</CODE> directory is located by the compiler before the standard Ciao library. The same applies for when running all of them if the library loading is dynamic. 


<P>
One way to do the above is using the <CODE>-u</CODE> compiler option. Assume the following file: 

<PRE>
     :- module(paths,[],[]).
     :- multifile library_directory/1.
     :- dynamic library_directory/1.
     :- initialization(asserta_fact(
	library_directory('/root/path/to/my/particular/application') )).
</PRE>

<P>
then you have file <CODE>webbased_common.pl</CODE> in a subdirectory <CODE>actmods</CODE> of the above cited path. You have to compile the name server, the active modules, and the rest of the application with: 

<PRE>
    ciaoc -u paths -s ...
</PRE>

<P>
to use your particular <CODE>webbased_common.pl</CODE> and to make executables statically link libraries. If they are dynamic, then you have to provide for the above library_directory path to be set up upon execution. This can be done, for example, by including module <CODE>paths</CODE> into your executables. 


<P>
Addresses of active modules are saved by the name server in a subdirectory <CODE>webbased_db</CODE> of the directory where you start it --see <CODE>examples/webbased_server/webbased_db/webbased_server</CODE>). This allows to restart the server right away if it dies (since it saves its state). This directory should be cleaned up regularly of addresses of active modules which are no more active. To do this, stop the server --by killing it (its pid is in <CODE>PATH/FILE</CODE>), and restart it after cleaning up the files in the above mentioned directory. 




<H3><A NAME="SEC448" HREF="ciao_toc.html#TOC448">Active modules as agents</A></H3>

<P>
It is rather easy to turn Ciao active modules into agents for some kind of applications. The directory <CODE>examples/agents</CODE> contains a (hopefully) self-explanatory example. 




<H2><A NAME="SEC449" HREF="ciao_toc.html#TOC449">Usage and interface (<CODE>actmods</CODE>)</A></H2>

<div class="cartouche">

<UL>

<LI><STRONG>Library usage:</STRONG>

<CODE>:- use_package(actmods).</CODE>

or

<CODE>:- module(...,...,[actmods]).</CODE>

<LI><STRONG>New declarations defined:</STRONG>

<A NAME="IDX5445"></A>
<CODE>use_active_module/2</CODE>.

</UL>

</div class="cartouche">



<H2><A NAME="SEC450" HREF="ciao_toc.html#TOC450">Documentation on new declarations (<CODE>actmods</CODE>)</A></H2>
<P>
<A NAME="IDX5446"></A>
<A NAME="IDX5447"></A>
<DL>
<DT><span class="define">DECLARATION:</span> <B>use_active_module/2:</B>
<DD><A NAME="IDX5448"></A>


<P>
<STRONG>Usage:</STRONG> :- <CODE>use_active_module(AModule, Imports)</CODE>.

<UL>
<LI><EM>Description:</EM> Specifies that this code imports from the <EM>active module</EM> defined in <CODE>AModule</CODE> the predicates in <CODE>Imports</CODE>. The imported predicates must be exported by the active module.

<LI><EM>The following properties should hold at call time:</EM>

<CODE>AModule</CODE> is a source name.
 (<CODE>streams_basic:sourcename/1</CODE>)

<CODE>Imports</CODE> is a list of <CODE>predname</CODE>s.
 (<CODE>basic_props:list/2</CODE>)
</UL>

</DL>



<H2><A NAME="SEC451" HREF="ciao_toc.html#TOC451">Known bugs and planned improvements (<CODE>actmods</CODE>)</A></H2>


<UL>

<LI>

The package provides no means for security: the accessing application must take care of this (?).

<LI>

It can happen that there is a unique process for an active module serving calls from several different simultaneous executions of the same application. In this case, there might be unwanted interactions (e.g., if the active module has state).

<LI>

Applications may fail if the name server or an active module is restarted during execution of the application (since they restart at a different port than the one cached by the application).

<LI>

One may want name servers to reside at a fixed and known machine and port number (this is known as a <EM>service</EM> and is defined in <CODE>/etc/services</CODE> in a Un*x machine). Currently, the port number changes in each invocation of the server.

<LI>

One may want to have one name server dedicated to a single application. Currently, there is no easy way to do this.
</UL>

<P><HR><P>
Go to the <A HREF="ciao_1.html">first</A>, <A HREF="ciao_107.html">previous</A>, <A HREF="ciao_109.html">next</A>, <A HREF="ciao_241.html">last</A> section, <A HREF="ciao_toc.html">table of contents</A>.
</BODY>
</HTML>