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