/interpreter/tags/at2-build060407/src/edu/vub/at/actors/natives/ELVirtualMachine.java

http://ambienttalk.googlecode.com/ · Java · 270 lines · 124 code · 39 blank · 107 comment · 7 complexity · b8a0f2543e66aa15082bf5f7009a5782 MD5 · raw file

  1. /**
  2. * AmbientTalk/2 Project
  3. * ELVirtualMachine.java created on Nov 1, 2006 at 8:32:31 PM
  4. * (c) Programming Technology Lab, 2006 - 2007
  5. * Authors: Tom Van Cutsem & Stijn Mostinckx
  6. *
  7. * Permission is hereby granted, free of charge, to any person
  8. * obtaining a copy of this software and associated documentation
  9. * files (the "Software"), to deal in the Software without
  10. * restriction, including without limitation the rights to use,
  11. * copy, modify, merge, publish, distribute, sublicense, and/or
  12. * sell copies of the Software, and to permit persons to whom the
  13. * Software is furnished to do so, subject to the following
  14. * conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be
  17. * included in all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  20. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  21. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  22. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  23. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  24. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  26. * OTHER DEALINGS IN THE SOFTWARE.
  27. */
  28. package edu.vub.at.actors.natives;
  29. import edu.vub.at.actors.eventloops.Event;
  30. import edu.vub.at.actors.eventloops.EventLoop;
  31. import edu.vub.at.actors.id.ATObjectID;
  32. import edu.vub.at.actors.id.ActorID;
  33. import edu.vub.at.actors.id.VirtualMachineID;
  34. import edu.vub.at.actors.net.ConnectionListenerManager;
  35. import edu.vub.at.actors.net.VMAddressBook;
  36. import edu.vub.at.actors.net.cmd.CMDHandshake;
  37. import edu.vub.at.actors.net.cmd.CMDObjectTakenOffline;
  38. import edu.vub.at.actors.net.comm.Address;
  39. import edu.vub.at.actors.net.comm.CommunicationBus;
  40. import edu.vub.at.actors.net.comm.NetworkException;
  41. import edu.vub.at.objects.ATAbstractGrammar;
  42. import edu.vub.at.util.logging.Logging;
  43. import java.util.Hashtable;
  44. /**
  45. * A ELVirtualMachine represents a virtual machine which hosts several actors. The
  46. * virtual machine is in charge of creating connections with other virtual machines
  47. * and orchestrates the broadcasting of its presence, the exchange of service
  48. * descriptions and messages. It also contains a set of runtime parameters (such as
  49. * the objectpath and initfile) which are needed to initialise a new actor.
  50. *
  51. * @author tvcutsem
  52. * @author smostinc
  53. */
  54. public final class ELVirtualMachine extends EventLoop {
  55. public static final String _DEFAULT_GROUP_NAME_ = "AmbientTalk";
  56. /** startup parameter to the VM: the code of the init.at file to use */
  57. private final ATAbstractGrammar initialisationCode_;
  58. /** startup parameter to the VM: the list of fields to be initialized in every hosted actor */
  59. private final SharedActorField[] sharedFields_;
  60. /** the VirtualMachineID of this VM */
  61. private final VirtualMachineID vmId_;
  62. /**
  63. * A table mapping VM GUIDs to Address objects.
  64. * Each time a VM connects, it sends its VirtualMachineID and an entry
  65. * mapping that VirtualMachineID to its current Address is registered in this table. When a remote reference
  66. * needs to send a message to the remote object, the VM is contacted based on its VirtualMachineID and this
  67. * table. When a VM disconnects, the disconnecting address is removed from this table.
  68. */
  69. public final VMAddressBook vmAddressBook_;
  70. /** a table mapping actor IDs to local native actors (int -> ELActor) */
  71. private final Hashtable localActors_;
  72. /** the communication bus for this Virtual Machine */
  73. public final CommunicationBus communicationBus_;
  74. /** manager for disconnection and reconnection observers */
  75. public final ConnectionListenerManager connectionManager_;
  76. /** the actor responsible for hosting the publications and subscriptions of this VM's actors */
  77. public final ELDiscoveryActor discoveryActor_;
  78. /**
  79. * Construct a new AmbientTalk virtual machine where...
  80. * @param initCode is the code to be executed in each new created actor (the content of the init.at file)
  81. * @param fields are all of the fields that should be present in each new created actor (e.g. the 'system' object of IAT)
  82. * @param groupName is the name of the overlay network to join
  83. */
  84. public ELVirtualMachine(ATAbstractGrammar initCode, SharedActorField[] fields, String groupName) {
  85. super("virtual machine");
  86. // used to initialize actors
  87. initialisationCode_ = initCode;
  88. sharedFields_ = fields;
  89. // used to allow actors to send messages to remote vms/actors
  90. vmAddressBook_ = new VMAddressBook();
  91. vmId_ = new VirtualMachineID();
  92. localActors_ = new Hashtable();
  93. discoveryActor_ = new ELDiscoveryActor(this);
  94. // initialize the message dispatcher using a JChannel
  95. connectionManager_ = new ConnectionListenerManager();
  96. communicationBus_ = new CommunicationBus(this, groupName);
  97. Logging.VirtualMachine_LOG.info(this + ": VM created on network " + groupName);
  98. }
  99. public static final ELVirtualMachine currentVM() {
  100. return ELActor.currentActor().getHost();
  101. }
  102. public VirtualMachineID getGUID() { return vmId_; }
  103. public ATAbstractGrammar getInitialisationCode() {
  104. return initialisationCode_;
  105. }
  106. public SharedActorField[] getFieldsToInitialize() {
  107. return sharedFields_;
  108. }
  109. public ELVirtualMachine getHost() { return this; }
  110. /**
  111. * An event loop handles events by dispatching to the event itself.
  112. */
  113. public void handle(Event event) {
  114. // make the event process itself
  115. event.process(this);
  116. }
  117. /**
  118. * returns the local actor corresponding to the given actor Id.
  119. * This method synchronizes on the localActors_ table to ensure that
  120. * insertion and lookup are properly synchronized.
  121. */
  122. public ELActor getActor(ActorID id) {
  123. ELActor entry;
  124. synchronized (localActors_) {
  125. entry = (ELActor) localActors_.get(id);
  126. }
  127. if (entry != null) {
  128. return entry;
  129. } else {
  130. throw new RuntimeException("Asked for unknown actor id: " + id);
  131. }
  132. }
  133. /**
  134. * Signals the creation of a new actor on this virtual machine.
  135. */
  136. public void actorCreated(ELActor actor) {
  137. // lock the localActors_ table first to ensure addition is
  138. // atomic w.r.t. lookup in getActor
  139. synchronized (localActors_) {
  140. localActors_.put(actor.getActorID(), actor);
  141. }
  142. }
  143. /**
  144. * Signals that this VM can connect to the underlying network channel
  145. * and can start distributed interaction.
  146. */
  147. public void event_goOnline() {
  148. this.receive(new Event("goOnline") {
  149. public void process(Object myself) {
  150. try {
  151. Address myAddress = communicationBus_.connect();
  152. Logging.VirtualMachine_LOG.info(this + ": interpreter online, address = " + myAddress);
  153. } catch (NetworkException e) {
  154. Logging.VirtualMachine_LOG.fatal(this + ": could not connect to network:", e);
  155. }
  156. }
  157. });
  158. }
  159. /**
  160. * Signals that this VM must disconnect from the underlying discovery channel and communication bus
  161. */
  162. public void event_goOffline() {
  163. this.receive(new Event("goOffline") {
  164. public void process(Object myself) {
  165. try {
  166. communicationBus_.disconnect();
  167. Logging.VirtualMachine_LOG.info(this + ": interpreter offline");
  168. } catch (Exception e) {
  169. Logging.VirtualMachine_LOG.fatal(this + ": error while going offline:", e);
  170. }
  171. }
  172. });
  173. }
  174. /**
  175. * Notifies the discovery manager that a VM has joined the network.
  176. * This VM may be a first-time participant or it may be a previously
  177. * disconnected VM that has become reconnected.
  178. *
  179. * This VM will handshake with the connected VM to exchange their actual
  180. * {@link VirtualMachineID}s rather than their network addresses.
  181. */
  182. public void event_memberJoined(final Address remoteVMAddress) {
  183. this.receive(new Event("memberJoined("+remoteVMAddress+")") {
  184. public void process(Object myself) {
  185. Logging.VirtualMachine_LOG.info(this + ": VM connected: " + remoteVMAddress);
  186. // send a handshake message to exchange IDs
  187. new CMDHandshake(vmId_).send(communicationBus_, remoteVMAddress);
  188. }
  189. });
  190. }
  191. public void event_memberLeft(final Address virtualMachine) {
  192. this.receive(new Event("memberLeft("+virtualMachine+")") {
  193. public void process(Object myself) {
  194. Logging.VirtualMachine_LOG.info(this + ": VM disconnected: " + virtualMachine);
  195. // Identify the VirtualMachineID that corresponds to this address
  196. VirtualMachineID disconnected = vmAddressBook_.getGUIDOf(virtualMachine);
  197. // disconnected may be null if the memberJoined event was ignored because this VM
  198. // was already offline when the event was being processed.
  199. if(disconnected != null) {
  200. // delete entries mapping to Address from the vm Address Book table first,
  201. // so sending threads may have 'premonitions' that they are no longer connected
  202. vmAddressBook_.removeEntry(virtualMachine);
  203. // properly (but synchronously) notify all remote references of a disconnection
  204. connectionManager_.notifyDisconnected(disconnected);
  205. }
  206. }
  207. });
  208. }
  209. /* ==========================
  210. * == Actor -> VM Protocol ==
  211. * ========================== */
  212. // All methods prefixed by event_ denote asynchronous message sends that will be
  213. // scheduled in the receiving event loop's event queue
  214. /**
  215. * Event that signals the deletion of an object from the export table of an
  216. * actor on this virtual machine.
  217. */
  218. public void event_objectTakenOffline(final ATObjectID objId, final Address receiver) {
  219. this.receive( new Event("objectTakenOffline(" + objId +")") {
  220. public void process(Object myself){
  221. if ( receiver == null){
  222. //broadcast to other virtual machines that an object has gone offline.
  223. new CMDObjectTakenOffline(objId).broadcast(communicationBus_);
  224. } else{
  225. //sending to a known virtual machine in response to an XObjectOffline exception.
  226. new CMDObjectTakenOffline(objId).send(communicationBus_, receiver);
  227. }
  228. }
  229. });
  230. }
  231. }