Object-Oriented Models ====================== Mobile Agents ============= Mobile Objects Autonomous Objects Messengers Intelligent Messages Agents consist of - code (behavior) - data - execution state - itineray bundled together and can move as a single unit. Distributed Systems - Object components must be platform-independent or convertible from and into portable forms Computational Characteristics - Object passing (object can move) - Autonomous (agent itself decides what to do and where to go) - Asynchronous (own thread of execution) - Local interaction (interaction with other objects/agents on same node) - Disconnected operation (performs task even when network connection closed) - Parallel execution (multiple agents can be dispatched to different sites) Usage patterns - messenger-receiver (messenger aglet dispatched to receiver aglet to deliver messages) - master-slave (master aglet dispatches slave aglet to remote site to perform task; when slave has completed itineray, it returns and reports to master aglet) e.g. accessing Databases Client creates agent to gather information from several databases. Client provides itineray and sends it off to first database server. Itinery controls routing of agent, on each server agent collects data and eventually returns to dispatcher. e.g. distributed meeting scheduling Aglet dispatched to arrange a meeting. Agent uses itinery to visit other hosts in order to negotiate an acceptable meeting schedule with participants. At each host local calendar system is accomodated. When negotiation has finished, agent notifies all participants of meeting time and place. e.g. auction Client dispatches agent to offer item for sale. Other clients dispatch agents to search for specific items. When agents meet, they bargain. "Smarter" agents make better baargains than less clever ones. - notifier-notification (notifier aglet is dispatched to remote site to monitor events of interest; on event, notifier aglet sends back notification via messenger aglet) e.g. Web site monitor Web browser dispatches agent to Web site. Agent monitors site or specific documents for updates. When a document is updated, agent sends messenger to owner or returns itself. Messengers ---------- University of California at Irvine Autonomous objects executing program consisting of - computational commands (performed on local node) - navigational commands (go to other node) Computational commands operating on variables: - messenger variables: local to messenger - node variables: resident in nodes - link variables: associated with link along which messenger arrived Navigational commands: - move_to_node(S): go to specific node - replicate_along_link(L): replicate messenger along all links labelled L (optional, default: all links) and terminate - send_along_new_link(L): like previous but creates new link for each messenger sent (with new node/interpreter at end of link; additional parameters specifiy how node/links are mapped onto physical network) - terminate: discard messenger Execution model - daemon network created on physical network (running messenger interpreters) - logical network: application-specific computation network created by messenger program on underlying daemon network SLIDE: Figure 1, page 6 SLIDE: Figure 2, page 7 Messengers: A Distributed Computing Environment for Autonomous Objects Example: network control computing in unknown or dynamic topologies find shortest-path spanning tree in weighted unidirected network with root S move_to_node(S) M_DIST = 0 // messenger variable N_DIST = 0 // node variable M_PREDECESSOR = read_node_address() repeat replacate_along_links(ALL) M_DIST = M_DIST + L_WEIGHT // link variable if N_DIST != empty and M_DIST >= N_DIST terminate N_DIST = M_DIST N_PREDECESSOR = M_PREDECESSOR until terminate_condition - M_DIST records distance of messenger from S - N_DIST records smallest M_DIST value of any messenger visiting node - M_PREDECESSOR records address of predecessor node - N_PREDECESSOR records address of predecessor node from which messenger with smallest M_DIST value has arrived IBM Aglets ---------- 1996 proposal for distributed object computing based on WWW/Java ATP (Agent Transfer Protocol) - protocol for transfer of mobile agents (cf. HTTP and HTML documents) - URL for resource location Aglets (Agile agent) - mobile agents implemented in Java - framework of classes for aglet construction Aglet Server - run on every site and respond to ATP requests Aglet launcher - aglet may be dispatched and retracted from an applet (and thus from a web page) Sample Code: import aglet.*; import java.net.URL; public class DispatchingExample extends Aglet { private boolean _theRemote = false; public void onDispatching(URL url) { // Print to the console... } public void onArrival() { _theRemote = true; //-- Yes, I am the remote aglet. // Print to the console... } public void run() { if (!_theRemote) { // The original aglet runs here try { URL destination = getAgletContext().getHostingURL(); dispatch(destination); // You should never get here! } catch (Exception e) { System.out.println(e.getMessage()); } } else { // The remote aglet runs here... } } } (Java Aglet Application Programming Interface (JAPPI) White Paper - Draft) SLIDE Searcher Application Searcher + SearcherSlave search for files with specific name patterns: stationary aglet (Searcher) dispatches mobile aglet (SearcherSlave) to remote location where it will search for files whose names match patterns, go to the next host, and eventually return to the Searcher. /* * @(#)Searcher.java * * The program is provided "as is" without any warranty express or * implied, including the warranty of non-infringement and the implied * warranties of merchantibility and fitness for a particular purpose. * IBM will not be liable for any damages suffered by you as a result * of using the Program. In no event will IBM be liable for any * special, indirect or consequential damages or lost profits even if * IBM has been advised of the possibility of their occurrence. IBM * will not be liable for any third party claims against you. */ package ibm.aglets.samples; import aglet.*; import ibm.aglets.patterns.*; import ibm.aglets.util.*; import java.net.URL; import java.net.MalformedURLException; import java.io.IOException; import java.util.Vector; import java.util.Properties; /** * Class Searcher is used to retrieve local user information * from a remote aglet server. Given a list of URLs it will dispatch * a slave (the SearchSlave class) to search for files whose * names are matched with a specific string. The slave will return * with the information to be displayed by the master. * * @see SearcherWindow * @see SearcherSlave * @version 1.00 96/08/18 * @author Yoshiaki Mima * @author Yariv Aridor */ public class Searcher extends SampleAglet { //-- name of the slave's class private final static String SlaveClassName = "ibm.aglets.samples.SearcherSlave"; //-- the result of the search private Vector _fileList = null; //-- Message handler. public boolean handleMessage(Message msg) { if ("status report".equals(msg.kind)) { message((String)(msg.getArg())); return false; } else return super.handleMessage(msg); } /** * The master's callback. The entry point for the returning slave. * This method is a part of the Master-Slave usage pattern. * @param s the slave. * @param arg the result of the slave's work. */ protected synchronized void callback(Object arg) { String ni; // Slave is back... setTheMessage("Searcher has returned"); _fileList = (Vector)arg; for (int i = 0; i < _fileList.size(); i++) { SearcherInfo si= (SearcherInfo)(_fileList.elementAt(i)); Vector v = si.getFileList(); for (int j=0; j < v.size(); j++) { ((SearcherWindow)_msw).addResultList( SearcherInfo.getFullPathName(si.getHostURL(), (String)(v.elementAt(j)))); } } } //-- display the files found for a specific URL. // synchronized void showPartOfResult(URL url) { URL url1 = null; for (int i = 0; i < _fileList.size(); i++) { SearcherInfo si= (SearcherInfo)(_fileList.elementAt(i)); try { url1 = new URL(url, si.getHostURL().toString()); } catch (Exception e) {} if (url.equals(url1)) { Vector v = si.getFileList(); for (int j=0; j < v.size(); j++) { ((SearcherWindow)_msw).addResultList( SearcherInfo.getFullPathName(url, (String)(v.elementAt(j)))); } } } } /** * The main entry point of the aglet's own thread. */ public void run() { super.run(); try { _msw = new SearcherWindow(this); contactWB(FILE_DEMO_WB_NAME); } catch (AgletException ae) { inError(ae.getMessage()); } } /** * Dispatch a slave. * @param destinations the destination URLs. * @param string the string to match against filenames. */ void go(Vector destinations, String str) { super.go((URL)(destinations.firstElement())); try { Slave.create(null, SlaveClassName, getAgletContext(), this, new SeqItinerary(destinations), str); } catch (IOException ae) { inError(ae.getMessage()); } catch (AgletException ae) { // Aglet creation failed. inError(ae.getMessage()); } } //-- Write new values to the WhiteBoard. // void getNewFieldValues(Properties p) { try { getAgletContext().writeWBoard(FILE_DEMO_WB_NAME,p); } catch (AgletException ae) { inError(ae.getMessage()); } } } /* * @(#)SearcherSlave.java * * The program is provided "as is" without any warranty express or * implied, including the warranty of non-infringement and the implied * warranties of merchantibility and fitness for a particular purpose. * IBM will not be liable for any damages suffered by you as a result * of using the Program. In no event will IBM be liable for any * special, indirect or consequential damages or lost profits even if * IBM has been advised of the possibility of their occurrence. IBM * will not be liable for any third party claims against you. */ package ibm.aglets.samples; import aglet.*; import ibm.aglets.patterns.*; import java.util.Enumeration; import java.util.Vector; import java.util.StringTokenizer; import java.net.URL; import java.net.MalformedURLException; import java.io.*; /** * The SearcherSlave class is a aglet for the Searcher. * * @see Searcher * @version 1.00 96/07/24 * @author Danny B. Lange * @author Yoshiaki Mima * @author Yariv Aridor */ public class SearcherSlave extends Slave { private Vector _fileList = null; protected synchronized void initializeJob () { RESULT = new Vector(); } protected synchronized void doJob() throws AgletException { String filename, readPath; filename = (String)ARGUMENT; _fileList = new Vector(); //-- a slave is always untrusted readPath = getAgletContext().getProperty("aglets.tahiti.untrusted.read", ""); if (!readPath.equals("")) { find(filename.toLowerCase(), //-- case insensitive readPath.toLowerCase()); } ((Vector)RESULT).addElement( new SearcherInfo( getAgletContext().getHostingURL(), _fileList)); reportMaster("Completed search"); } //-- report the Master // private void reportMaster(String msg) { AgletContext ac; try { ac = getAgletContext(); Messenger.create(ac, getOrigin(), getMaster(), new Message ("status report", ac.getHostingURL().toString() + ":" + msg)); } catch (IOException ae) { //-- we give up this report. } catch (AgletException ae) { //-- we give up this report. } } // looking for matched files (case insensitive) // private void find(String s, String paths) { Enumeration e = makePathList(paths).elements(); for (; e.hasMoreElements(); ) { File f = (File)e.nextElement(); matchFiles(s, f); } } //-- match a filename with a given string. If the file //-- is a directory, make recursive match. // private void matchFiles(String s, File f) { if (f.isFile()) { if (f.getAbsolutePath().toLowerCase().indexOf(s) > -1) _fileList.addElement(f.getAbsolutePath()); } else if (f.isDirectory()) { // Get the directory list and perform a recursive descent. String[] dir = f.list(); for (int i = 0; i < dir.length; i++) { matchFiles(s, new File(f, dir[i])); } } } //-- enumerate all allowed read paths.. // private Vector makePathList(String p) { char ps = File.pathSeparatorChar; Vector pathList = new Vector(); StringTokenizer st = new StringTokenizer(p, ps + ";" , false); while (st.hasMoreTokens()) { pathList.addElement(new File(st.nextToken())); /* // '/' is the universal path separator for path checking path = path.replace(File.separatorChar, '/'); */ } return pathList; } //-- enumerate all allowed read paths.. // private Vector makePathList1(String p) { // Separates each path in the path list and creates a vector of paths. char ps = File.pathSeparatorChar; Vector pathList = new Vector(); int to = p.indexOf(ps); while (to < p.length()) { if (to == -1) { if (p.length() > 0) { String pp = p.substring(0).trim(); if (!pp.equals("")) pathList.addElement(new File(pp)); } break; } String pp = p.substring(0, to).trim(); if (!pp.equals("")) pathList.addElement(new File(pp)); if (p.length() > to + 1) { p = p.substring(to + 1); to = p.indexOf(ps); } else break; } return pathList; } }