PageRenderTime 28ms CodeModel.GetById 13ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/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 */
 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		
111		// initialize the message dispatcher using a JChannel
112		connectionManager_ = new ConnectionListenerManager();
113		communicationBus_ = new CommunicationBus(this, groupName);
114		
115		Logging.VirtualMachine_LOG.info(this + ": VM created on network " + groupName);
116	}
117	
118	public static final ELVirtualMachine currentVM() {
119		return ELActor.currentActor().getHost();
120	}
121		
122	public VirtualMachineID getGUID() { return vmId_; }
123		
124	public ATAbstractGrammar getInitialisationCode() {
125		return initialisationCode_;
126	}
127
128	public SharedActorField[] getFieldsToInitialize() {
129		return sharedFields_;
130	}
131	
132	public ELVirtualMachine getHost() { return this; }
133
134	/**
135	 * An event loop handles events by dispatching to the event itself.
136	 */
137	public void handle(Event event) {
138		// make the event process itself
139		event.process(this);
140	}
141	
142	/**
143	 * returns the local actor corresponding to the given actor Id.
144	 * This method synchronizes on the localActors_ table to ensure that
145	 * insertion and lookup are properly synchronized.
146	 */
147	public ELActor getActor(ActorID id) {
148		ELActor entry;
149		synchronized (localActors_) {
150			entry = (ELActor) localActors_.get(id);
151		}
152		if (entry != null) {
153			return entry;
154		} else {
155			throw new RuntimeException("Asked for unknown actor id: " + id);
156		}
157	}
158	
159	/**
160	 * Signals the creation of a new actor on this virtual machine.
161	 */
162	public void actorCreated(ELActor actor) {
163		// lock the localActors_ table first to ensure addition is
164		// atomic w.r.t. lookup in getActor
165		synchronized (localActors_) {
166			localActors_.put(actor.getActorID(), actor);
167		}
168	}
169	
170	/**
171	 * Signals that this VM can connect to the underlying network channel
172	 * and can start distributed interaction.
173	 */
174	public void event_goOnline() {
175		this.receive(new Event("goOnline") {
176			public void process(Object myself) {
177				try {
178					Address myAddress = communicationBus_.connect();
179					Logging.VirtualMachine_LOG.info(this + ": interpreter online, address = " + myAddress);
180				} catch (NetworkException e) {
181					Logging.VirtualMachine_LOG.fatal(this + ": could not connect to network:", e);
182				}
183			}
184		});
185	}
186	
187	/**
188	 * Signals that this VM must disconnect from the underlying discovery channel and communication bus
189	 */
190	public void event_goOffline() {
191		this.receive(new Event("goOffline") {
192			public void process(Object myself) {
193				try {
194					communicationBus_.disconnect();
195					Logging.VirtualMachine_LOG.info(this + ": interpreter offline");
196				} catch (Exception e) {
197					Logging.VirtualMachine_LOG.fatal(this + ": error while going offline:", e);
198				}
199			}
200		});
201	}
202	
203	/**
204	 * Notifies the discovery manager that a VM has joined the network.
205	 * This VM may be a first-time participant or it may be a previously
206	 * disconnected VM that has become reconnected.
207	 * 
208	 * This VM will handshake with the connected VM to exchange their actual
209	 * {@link VirtualMachineID}s rather than their network addresses.
210	 */
211	public void event_memberJoined(final Address remoteVMAddress) {
212		this.receive(new Event("memberJoined("+remoteVMAddress+")") {
213			public void process(Object myself) {
214				Logging.VirtualMachine_LOG.info(this + ": VM connected: " + remoteVMAddress);
215				// send a handshake message to exchange IDs
216				new CMDHandshake(vmId_).send(communicationBus_, remoteVMAddress);
217			}
218		});
219	}
220	
221	public void event_memberLeft(final Address virtualMachine) {
222		this.receive(new Event("memberLeft("+virtualMachine+")") {
223			public void process(Object myself) {
224				Logging.VirtualMachine_LOG.info(this + ": VM disconnected: " + virtualMachine);
225				
226				// Identify the VirtualMachineID that corresponds to this address
227				VirtualMachineID disconnected = vmAddressBook_.getGUIDOf(virtualMachine);
228				
229				// disconnected may be null if the memberJoined event was ignored because this VM 
230				// was already offline when the event was being processed.
231				if(disconnected != null) {
232					// delete entries mapping to Address from the vm Address Book table first, 
233					// so sending threads may have 'premonitions' that they are no longer connected
234					vmAddressBook_.removeEntry(virtualMachine);
235					
236					// properly (but synchronously) notify all remote references of a disconnection 
237					connectionManager_.notifyDisconnected(disconnected);
238				}
239			}
240		});
241	}
242	
243	
244	/* ==========================
245	 * == Actor -> VM Protocol ==
246	 * ========================== */
247	
248	// All methods prefixed by event_ denote asynchronous message sends that will be
249	// scheduled in the receiving event loop's event queue
250	
251	/**
252	 * Event that signals the deletion of an object from the export table of an
253	 * actor on this virtual machine.
254	 */
255	public void event_objectTakenOffline(final ATObjectID objId, final Address receiver) {
256		 this.receive( new Event("objectTakenOffline(" + objId +")") {
257			 public void process(Object myself){
258				 if ( receiver == null){
259					 //broadcast to other virtual machines that an object has gone offline.
260					 new CMDObjectTakenOffline(objId).broadcast(communicationBus_);
261				 } else{
262					 //sending to a known virtual machine in response to an XObjectOffline exception.
263					 new CMDObjectTakenOffline(objId).send(communicationBus_, receiver);
264				 }
265				 
266			 }
267		 });
268	}
269	
270}