270 likes | 381 Views
Lecture 21 – April 4, 2002. Dynamic Loading Communication in Bond Message delivery Internal and external message format KQML Synchronous and asynchrounous communication Events – monitoring Communication Engines Base 64 encoding Virtual Networks of Objects.
E N D
Lecture 21 – April 4, 2002 • Dynamic Loading • Communication in Bond • Message delivery • Internal and external message format • KQML • Synchronous and asynchrounous communication • Events – monitoring • Communication Engines • Base 64 encoding • Virtual Networks of Objects
public class bondLoader extends bondObject { public Vector defaultpath = null; ClassLoader cloader = null; public bondLoader() { defaultpath = new Vector(); defaultpath.addElement("bond.core."); defaultpath.addElement("bond.services."); defaultpath.addElement("bond.agent."); defaultpath.addElement("bond.application."); defaultpath.addElement("bond.application.TupleSpace."); }
/** Create object "name" with default constructor given "searchpath" */ public Object load(String name, Vector searchpaths) { Object o = null; Class cl; try { if ((cl = loadClass(name, searchpaths)) != null) { o = cl.newInstance(); } } catch(IllegalAccessException cnfe) { } catch(InstantiationException ie) { } return o; }
/** Load a local class given its "name" */ public Class loadClass(String name, Vector searchpaths) { String completename; for(int i=0; i!=searchpaths.size(); i++) { try { Class cl = Class.forName(makeName (name, (String)searchpaths.elementAt(i))); return cl; } catch(ClassNotFoundException cnfe) { } catch(Exception ex) { } }
/** Load classes remotely */ if (cloader == null) { • String c_repository = System.getProperty ("bond.current.strategy.repository"); String repository = System.getProperty ("bond.strategy.repository"); if (c_repository != null && repository != null) { try { URL urlList[] = {new URL(c_repository), new URL(repository)}; cloader = new URLClassLoader(urlList); } catch (MalformedURLException e) { } } else if (repository != null) { try { URL urlList[] = {new URL (repository)}; cloader = new URLClassLoader(urlList); } catch (MalformedURLException e) { } } } for (int i = 0; i < searchpaths.size(); i++) { try { Class cl = Class.forName(makeName(name, (String)searchpaths.elementAt(i)), true, cloader); return cl; } catch (ClassNotFoundException cnfe) { } catch(Exception ex) { } } return null; } }
Communication • Multiple external message formats, • Multiple transport mechanism, • Dynamic collection of objects, • Make communication simple.
Internal message format • Internal format: unordered collection of name-value pairs implemented as dynamic properties of the bondMessage object. • The name is a string • The value can be any bondObject • Reserved names: • Addressing variables (source, destination,…) • Message identifiers • Semantic identifiers (give the context of the message) • Hidden variables (variables removed before delivery)
External message representation • KQML • XML
Synchronous communication • ask() and waitReply() • ask() blocks the current thread, all other threads continue to run.
bondMessage question = new bondMessage(``(ask-one : content get :value i :)'', ``PropertyAccess''); bondMessage rep = bs.ask(question, this, 10000); if (rep == null) { System.err.println(``Timeout of 10s exceeded''); } else { System.out.println(``Field i of remote object is''+ (String)rep.getParameter(``value'')); }
bondMessage question = new bondMessage(``(ask-one :content get :value i :)'', ``PropertyAccess''); question.needsReply(); bs.say(question, this); ... code executed before the reply ... rep = question.waitReply(10000);
Asynchronous communication • The sender object uses the ask performative with reply-with field to send an asynchronous message. The communicator creates a message waiting slot for the sender object and deposits there a copy of the original message and the unique ID of the reply. • Eventually the receiver object replays using the tell performative. • When processing incoming messages, the communicator checks the waiting slot table for the unique ID of the message and if a waiting slot exists, the communicator delivers the message to it. • If the incoming messages has the on_reply field set then it is delivered directly, else it is delivered by the say() method.
Events/monitoring • An event could be the change of a property of a Bond object. • The set() function executed by the object being monitored notifies the monitor when a property subject to monitoring changes.
The communicator – the sending side for(every sent message) if (external format) transform message in internal format annotate with the sender address if (reply needed) { annotate with a unique reply-with field create a reply waiting slot } if (performative is subscribe) create an event waiting slot if (performative is unsubscribe) delete the event waiting slot if (need to send info to destination) annotate with the piggyback field pass the message to communicator engine
The communicator – the receiving side for(every incoming message) parse message remove the piggyback field if any if (has in-reply-to field) and (in-reply-to field maches a reply waiting slot) then { deliver to object waiting on the reply waiting slot delete the reply waiting slot } else if (performative is tell) and (sender maches an event waiting slot) then deliver to object waiting on the event waiting slot else lookup the destination object if (destination is alias) select an object with the alias at random else look up the object in local dir if (no object) { send error message to sender wake up a thread in the threadpool deliver the message using the thread } }
Communication Engines • Multiple communication engines: • TCP • UDP • Infospheres – based upon RMI • IP multicast • Each communication engine has a deamon to send and receive messages using the specific communication engine.
public class bondUDPDaemon extends bondObject { public bondUDPDaemon(int port) throws SocketException { super(false); udpSocket = new DatagramSocket(port); localport = port; } public int getLocalPort(){return localport;} public void send(InetAddress targetIP, int targetPort, String m) { bufOut = m.getBytes(); udpOutPacket = new DatagramPacket(bufOut, bufOut.length, targetIP, targetPort); try{udpSocket.send(udpOutPacket);} catch(IOException e){} }
public String receive() { try{ udpInPacket = new DatagramPacket(bufIn, 65535); udpSocket.receive(udpInPacket); InetAddress fromAddress = udpInPacket.getAddress(); fromHostname = fromAddress.getHostName(); fromPort = udpInPacket.getPort(); String mes = new String(udpInPacket.getData(), 0, udpInPacket.getLength()); return mes;} catch(IOException e){ return null; } }
Sending an object – realize() public void sendObject(bondShadow bs, bondObject bo, String in_reply_to) { bondExternalMessage bm = new bondExternalMessage(); bm.in_reply_to = in_reply_to; bm.bo = bo; String m = Base64.Object2String(bm); try{ InetAddress targetIP = InetAddress.getByName (bs.remote_address.ipaddress); bondUDPDaemon.send(targetIP, bs.remote_address.port, m);} catch(UnknownHostException e){e.printStackTrace();} }
Base 64 encoding • Take a 24 bit sequence from the source. If fewer than 24 bits are available use the "=" character for padding. • Separate the sequence into 4 six bit characters. • View each character as the lower 6 bits of an 8 bit character by padding it to the left with 00. With six bits one could encode 64 characters. • Use each 8 bit character constructed in the previous as an index into the Base64 alphabet: "ABCDEFGHIJKLMNOPQSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="