PageRenderTime 32ms CodeModel.GetById 21ms app.highlight 7ms RepoModel.GetById 2ms app.codeStats 0ms

/interpreter/tags/at2-build270707/src/edu/vub/at/actors/natives/ReceptionistsSet.java

http://ambienttalk.googlecode.com/
Java | 230 lines | 103 code | 29 blank | 98 comment | 20 complexity | 6650eda6b13d33f67feb2f1b35091937 MD5 | raw file
  1/**
  2 * AmbientTalk/2 Project
  3 * ReceptionistsSet.java created on Dec 5, 2006 at 10:58:44 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.ATFarReference;
 31import edu.vub.at.actors.id.ATObjectID;
 32import edu.vub.at.exceptions.InterpreterException;
 33import edu.vub.at.exceptions.XIllegalOperation;
 34import edu.vub.at.exceptions.XObjectOffline;
 35import edu.vub.at.objects.ATObject;
 36import edu.vub.at.objects.ATTypeTag;
 37import edu.vub.util.MultiMap;
 38
 39import java.lang.ref.WeakReference;
 40import java.util.HashMap;
 41import java.util.Hashtable;
 42import java.util.Iterator;
 43import java.util.Map;
 44
 45/**
 46 * An NATActorMirror's ReceptionistsSet keeps a mapping between identifiers and local objects
 47 * which allows resolving far objects to local ones. The ReceptionistsSet also stores
 48 * which actors refer to an object, which is the basis for a distributed garbage 
 49 * collection algorithm.
 50 *
 51 * @author smostinc
 52 */
 53public class ReceptionistsSet {
 54
 55    // TODO: these maps are not garbage-collected: obsolete entries are never removed
 56	
 57	/** object id (ATObjectID) -> local object (ATObject) */
 58	private final HashMap exportedObjectsTable_;	
 59	
 60	/**
 61	 * local object (ATObject) -> remote clients pointing to this object (Set of ATFarReference)
 62	 * @deprecated currently not in use
 63	 */
 64	private final MultiMap objectToClients_;
 65	
 66	private final ELActor owner_;
 67	
 68	/**
 69	 * a pool of remote object references: ensures that each ATObjectID is paired
 70	 * with a unique remote object reference (and corresponding outbox)
 71	 */
 72	private final Hashtable remoteReferences_;
 73	
 74	/**
 75	 * a pool of far object references: ensures that each ATObjectID is paired
 76	 * with a unique far object reference
 77	 */
 78	private final Hashtable farReferences_;
 79	
 80	public ReceptionistsSet(ELActor forActor) {
 81		owner_ = forActor;
 82		exportedObjectsTable_ = new HashMap();
 83		objectToClients_ = new MultiMap();
 84		remoteReferences_ = new Hashtable();
 85		farReferences_ = new Hashtable();
 86	}
 87	
 88	private NATRemoteFarRef createRemoteFarRef(ATObjectID objectId, ATTypeTag[] types) {
 89		NATRemoteFarRef farref;
 90		WeakReference pooled = (WeakReference) remoteReferences_.get(objectId);
 91		if (pooled != null) {
 92			farref = (NATRemoteFarRef) pooled.get();
 93			if (farref != null) {
 94				return farref;
 95			}
 96		}
 97		farref = new NATRemoteFarRef(objectId, owner_, types);
 98		remoteReferences_.put(objectId, new WeakReference(farref));
 99		return farref;
100	}
101	
102	private NATLocalFarRef createLocalFarRef(ELActor actor, ATObjectID objectId, ATTypeTag[] types) {
103		NATLocalFarRef farref;
104		WeakReference pooled = (WeakReference) farReferences_.get(objectId);
105		if (pooled != null) {
106			farref = (NATLocalFarRef) pooled.get();
107			if (farref != null) {
108				return farref;
109			}
110		}
111
112		farref = new NATLocalFarRef(actor, objectId, types, owner_);
113		farReferences_.put(objectId, new WeakReference(farref));
114		return farref;
115	}
116	
117	/**
118	 * Export a local object such that it now has a unique global identifier which
119	 * can be distributed to other actors. Only near references may be exported.
120	 * 
121	 * @param object - the local object to export to the outside world
122	 * @return a local remote reference denoting the local object
123	 * @throws XIllegalOperation - if object is a far reference
124	 */
125	public NATLocalFarRef exportObject(ATObject object) throws InterpreterException {
126		if (object.isFarReference()) {
127			throw new XIllegalOperation("Cannot export a far reference to " + object);
128		}
129		
130		// get the host VM
131		ELVirtualMachine currentVM = owner_.getHost();
132
133		// create a new unique ID for the exported object, but make sure that the unique identity
134		// remembers the VM id and actor ID from which the object originated
135		ATObjectID objId = new ATObjectID(currentVM.getGUID(), owner_.getActorID(), object.toString());
136		
137		// store the object if it was not previously exported */ 
138		if(!exportedObjectsTable_.containsKey(objId)) {
139			exportedObjectsTable_.put(objId, object);
140		}
141		
142		// copy types of local object
143		ATObject[] origTypes = object.meta_typeTags().asNativeTable().elements_;
144		ATTypeTag[] types = new ATTypeTag[origTypes.length];
145		System.arraycopy(origTypes, 0, types, 0, origTypes.length);
146		return createLocalFarRef(owner_, objId, types);
147	}
148	
149	/**
150	 * Take offline a local object which was exported to the outside world. 
151	 *  
152	 * @param object - the local object exported to the outside world
153	 * @throws XIllegalOperation if the object was not found locally
154	 */
155	public void takeOfflineObject(ATObject object) throws XIllegalOperation {
156		
157		if (exportedObjectsTable_.containsValue(object)){
158			
159			for (Iterator i = exportedObjectsTable_.entrySet().iterator(); i.hasNext();) {
160				Map.Entry entry = (Map.Entry) i.next();
161				ATObject obj = (ATObject) entry.getValue();
162				
163				if (obj.equals(object)){
164					i.remove();
165					//notify the rest of VM that this object was taken offline
166					owner_.getHost().event_objectTakenOffline((ATObjectID) entry.getKey(), null);
167	
168				}
169			}
170		}else{
171			//the object was not previously exported or it has already been taken offline
172			//I don't know the objectId => throw XIllegalOperation
173			
174			throw new XIllegalOperation("Cannot take offline an object that is not online: " + object);
175		}
176	}
177	
178	/**
179	 * Try to resolve a remote object reference into a local (near) reference.
180	 * 
181	 * @param objectId the identifier of the remote object
182	 * @return either the local object corresponding to that identifier, or a far reference designating the id
183	 * @throws XObjectOffline if the object was not found locally
184	 */
185	public ATObject resolveObject(ATObjectID objectId, ATTypeTag[] types) throws XObjectOffline {
186		if (objectId.getActorId().equals(owner_.getActorID())) { // does objectId denote a local object?
187			
188			// object should be found in this actor
189			ATObject localObject = (ATObject) exportedObjectsTable_.get(objectId);
190			if (localObject == null) {
191				throw new XObjectOffline(objectId); // could not find the object locally
192			} else {
193				return localObject; // far ref now resolved to near ref
194			}
195			
196		} else if (objectId.isRemote()) { // the resolved object is not local
197			// the designated object does not live in this VM
198			return createRemoteFarRef(objectId, types);
199		} else {
200			// the designated object lives in the same VM as this actor
201			ELActor localActor = owner_.getHost().getActor(objectId.getActorId());
202			return createLocalFarRef(localActor, objectId, types);
203		}
204	}
205	
206	/**
207	 * Invoked whenever another actor is passed a reference to an object offering a
208	 * service on this actor. This is automatically done when serialising a local 
209	 * object during parameter or result passing. Upon serialisation of a far 
210	 * reference pointing to a service, a command object should be sent at the lowest
211	 * level to invoke this method as well.
212	 * 
213	 * This method is related to a simple reference listing strategy which should be 
214	 * the basis for a distributed garbage collector.
215	 * @deprecated currently not in use
216	 */
217	public void addClient(ATObject service, ATFarReference client) throws InterpreterException {
218		objectToClients_.put(service, client);
219	}
220
221	/**
222	 * Called upon the collection of a service on a remote device, or possibly when 
223	 * the conditions negotiated for the use of the service (e.g. its lease period)
224	 * have expired.
225	 * @deprecated currently not in use
226	 */
227	public void removeClient(ATObject service, ATFarReference client) throws InterpreterException {
228		objectToClients_.removeValue(service, client);
229	}
230}