PageRenderTime 46ms CodeModel.GetById 9ms app.highlight 30ms RepoModel.GetById 1ms app.codeStats 1ms

/interpreter/tags/at2dist130208/src/edu/vub/at/actors/natives/ELVirtualMachine.java

http://ambienttalk.googlecode.com/
Java | 271 lines | 125 code | 39 blank | 107 comment | 7 complexity | 9f7c87bc4c1aa2e3d92ac9fcbae71e92 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 */
 28package edu.vub.at.actors.natives;
 29
 30import edu.vub.at.actors.eventloops.Event;
 31import edu.vub.at.actors.eventloops.EventLoop;
 32import edu.vub.at.actors.id.ATObjectID;
 33import edu.vub.at.actors.id.ActorID;
 34import edu.vub.at.actors.id.VirtualMachineID;
 35import edu.vub.at.actors.net.ConnectionListenerManager;
 36import edu.vub.at.actors.net.VMAddressBook;
 37import edu.vub.at.actors.net.cmd.CMDHandshake;
 38import edu.vub.at.actors.net.cmd.CMDObjectTakenOffline;
 39import edu.vub.at.actors.net.comm.Address;
 40import edu.vub.at.actors.net.comm.CommunicationBus;
 41import edu.vub.at.actors.net.comm.NetworkException;
 42import edu.vub.at.objects.ATAbstractGrammar;
 43import edu.vub.at.util.logging.Logging;
 44
 45import java.util.Hashtable;
 46
 47/**
 48 * A ELVirtualMachine represents a virtual machine which hosts several actors. The 
 49 * virtual machine is in charge of creating connections with other virtual machines 
 50 * and orchestrates the broadcasting of its presence, the exchange of service 
 51 * descriptions and messages. It also contains a set of runtime parameters (such as
 52 * the objectpath and initfile) which are needed to initialise a new actor.
 53 *
 54 * @author tvcutsem
 55 * @author smostinc
 56 */
 57public final class ELVirtualMachine extends EventLoop {
 58	
 59	public static final String _DEFAULT_GROUP_NAME_ = "AmbientTalk";
 60		
 61	/** startup parameter to the VM: the code of the init.at file to use */
 62	private final ATAbstractGrammar initialisationCode_;
 63	
 64	/** startup parameter to the VM: the list of fields to be initialized in every hosted actor */
 65	private final SharedActorField[] sharedFields_;
 66	
 67	/** the VirtualMachineID of this VM */
 68	private final VirtualMachineID vmId_;
 69	
 70	/**
 71	 * A table mapping VM GUIDs to Address objects.
 72	 * Each time a VM connects, it sends its VirtualMachineID and an entry
 73	 * mapping that VirtualMachineID to its current Address is registered in this table. When a remote reference
 74	 * needs to send a message to the remote object, the VM is contacted based on its VirtualMachineID and this
 75	 * table. When a VM disconnects, the disconnecting address is removed from this table. 
 76	 */
 77	public final VMAddressBook vmAddressBook_;
 78	
 79	/** a table mapping actor IDs to local native actors (int -> ELActor) */
 80	private final Hashtable localActors_;
 81	
 82	/** the communication bus for this Virtual Machine */
 83	public final CommunicationBus communicationBus_;
 84	
 85	/** manager for disconnection and reconnection observers */
 86	public final ConnectionListenerManager connectionManager_;
 87	
 88	/** the actor responsible for hosting the publications and subscriptions of this VM's actors */
 89	public final ELDiscoveryActor discoveryActor_;
 90	
 91	/**
 92	 * Construct a new AmbientTalk virtual machine where...
 93	 * @param initCode is the code to be executed in each new created actor (the content of the init.at file)
 94	 * @param fields are all of the fields that should be present in each new created actor (e.g. the 'system' object of IAT)
 95	 * @param groupName is the name of the overlay network to join
 96	 */
 97	public ELVirtualMachine(ATAbstractGrammar initCode, SharedActorField[] fields, String groupName) {
 98		super("virtual machine");
 99		
100		// used to initialize actors
101		initialisationCode_ = initCode;
102		sharedFields_ = fields;
103		
104		// used to allow actors to send messages to remote vms/actors
105		vmAddressBook_ = new VMAddressBook();
106
107		vmId_ = new VirtualMachineID();
108		localActors_ = new Hashtable();
109		discoveryActor_ = new ELDiscoveryActor(this);
110		discoveryActor_.event_init();
111		
112		// initialize the message dispatcher using a JChannel
113		connectionManager_ = new ConnectionListenerManager();
114		communicationBus_ = new CommunicationBus(this, groupName);
115		
116		Logging.VirtualMachine_LOG.info(this + ": VM created on network " + groupName);
117	}
118	
119	public static final ELVirtualMachine currentVM() {
120		return ELActor.currentActor().getHost();
121	}
122		
123	public VirtualMachineID getGUID() { return vmId_; }
124		
125	public ATAbstractGrammar getInitialisationCode() {
126		return initialisationCode_;
127	}
128
129	public SharedActorField[] getFieldsToInitialize() {
130		return sharedFields_;
131	}
132	
133	public ELVirtualMachine getHost() { return this; }
134
135	/**
136	 * An event loop handles events by dispatching to the event itself.
137	 */
138	public void handle(Event event) {
139		// make the event process itself
140		event.process(this);
141	}
142	
143	/**
144	 * returns the local actor corresponding to the given actor Id.
145	 * This method synchronizes on the localActors_ table to ensure that
146	 * insertion and lookup are properly synchronized.
147	 */
148	public ELActor getActor(ActorID id) {
149		ELActor entry;
150		synchronized (localActors_) {
151			entry = (ELActor) localActors_.get(id);
152		}
153		if (entry != null) {
154			return entry;
155		} else {
156			throw new RuntimeException("Asked for unknown actor id: " + id);
157		}
158	}
159	
160	/**
161	 * Signals the creation of a new actor on this virtual machine.
162	 */
163	public void actorCreated(ELActor actor) {
164		// lock the localActors_ table first to ensure addition is
165		// atomic w.r.t. lookup in getActor
166		synchronized (localActors_) {
167			localActors_.put(actor.getActorID(), actor);
168		}
169	}
170	
171	/**
172	 * Signals that this VM can connect to the underlying network channel
173	 * and can start distributed interaction.
174	 */
175	public void event_goOnline() {
176		this.receive(new Event("goOnline") {
177			public void process(Object myself) {
178				try {
179					Address myAddress = communicationBus_.connect();
180					Logging.VirtualMachine_LOG.info(this + ": interpreter online, address = " + myAddress);
181				} catch (NetworkException e) {
182					Logging.VirtualMachine_LOG.fatal(this + ": could not connect to network:", e);
183				}
184			}
185		});
186	}
187	
188	/**
189	 * Signals that this VM must disconnect from the underlying discovery channel and communication bus
190	 */
191	public void event_goOffline() {
192		this.receive(new Event("goOffline") {
193			public void process(Object myself) {
194				try {
195					communicationBus_.disconnect();
196					Logging.VirtualMachine_LOG.info(this + ": interpreter offline");
197				} catch (Exception e) {
198					Logging.VirtualMachine_LOG.fatal(this + ": error while going offline:", e);
199				}
200			}
201		});
202	}
203	
204	/**
205	 * Notifies the discovery manager that a VM has joined the network.
206	 * This VM may be a first-time participant or it may be a previously
207	 * disconnected VM that has become reconnected.
208	 * 
209	 * This VM will handshake with the connected VM to exchange their actual
210	 * {@link VirtualMachineID}s rather than their network addresses.
211	 */
212	public void event_memberJoined(final Address remoteVMAddress) {
213		this.receive(new Event("memberJoined("+remoteVMAddress+")") {
214			public void process(Object myself) {
215				Logging.VirtualMachine_LOG.info(this + ": VM connected: " + remoteVMAddress);
216				// send a handshake message to exchange IDs
217				new CMDHandshake(vmId_).send(communicationBus_, remoteVMAddress);
218			}
219		});
220	}
221	
222	public void event_memberLeft(final Address virtualMachine) {
223		this.receive(new Event("memberLeft("+virtualMachine+")") {
224			public void process(Object myself) {
225				Logging.VirtualMachine_LOG.info(this + ": VM disconnected: " + virtualMachine);
226				
227				// Identify the VirtualMachineID that corresponds to this address
228				VirtualMachineID disconnected = vmAddressBook_.getGUIDOf(virtualMachine);
229				
230				// disconnected may be null if the memberJoined event was ignored because this VM 
231				// was already offline when the event was being processed.
232				if(disconnected != null) {
233					// delete entries mapping to Address from the vm Address Book table first, 
234					// so sending threads may have 'premonitions' that they are no longer connected
235					vmAddressBook_.removeEntry(virtualMachine);
236					
237					// properly (but synchronously) notify all remote references of a disconnection 
238					connectionManager_.notifyDisconnected(disconnected);
239				}
240			}
241		});
242	}
243	
244	
245	/* ==========================
246	 * == Actor -> VM Protocol ==
247	 * ========================== */
248	
249	// All methods prefixed by event_ denote asynchronous message sends that will be
250	// scheduled in the receiving event loop's event queue
251	
252	/**
253	 * Event that signals the deletion of an object from the export table of an
254	 * actor on this virtual machine.
255	 */
256	public void event_objectTakenOffline(final ATObjectID objId, final Address receiver) {
257		 this.receive( new Event("objectTakenOffline(" + objId +")") {
258			 public void process(Object myself){
259				 if ( receiver == null){
260					 //broadcast to other virtual machines that an object has gone offline.
261					 new CMDObjectTakenOffline(objId).broadcast(communicationBus_);
262				 } else{
263					 //sending to a known virtual machine in response to an XObjectOffline exception.
264					 new CMDObjectTakenOffline(objId).send(communicationBus_, receiver);
265				 }
266				 
267			 }
268		 });
269	}
270	
271}