/interpreter/tags/at_build150307/src/edu/vub/at/actors/net/MembershipNotifier.java

http://ambienttalk.googlecode.com/ · Java · 187 lines · 69 code · 25 blank · 93 comment · 11 complexity · a3b22cfbeb3470c40143c86754bfa76f MD5 · raw file

  1. /**
  2. * AmbientTalk/2 Project
  3. * MembershipNotifier.java created on Feb 16, 2007 at 1:14:08 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.net;
  29. import edu.vub.at.actors.id.GUID;
  30. import edu.vub.util.MultiMap;
  31. import java.util.Iterator;
  32. import java.util.Set;
  33. import java.util.Vector;
  34. import org.jgroups.Address;
  35. import org.jgroups.ExtendedReceiverAdapter;
  36. import org.jgroups.MembershipListener;
  37. import org.jgroups.View;
  38. /**
  39. * An instance of the class MembershipNotifier is registered with an instance of the JGroups
  40. * MessageDispatcher class as its MembershipListener. Whenever virtual machines connect or
  41. * disconnect from the multicast group, this object is notified. Its role is to propagate
  42. * these notifications to:
  43. * A) The AT/2 DiscoveryManager which is interested in contacting newly joined virtual machines
  44. * to see whether they provide some services that this VM requires.
  45. * B) All connected ConnectionListeners, which will usually be remote references pointing to
  46. * objects hosted by the connecting/disconnecting VM.
  47. *
  48. *
  49. * TODO: change Address keys of ConnectionListeners to GUIDs to support changing addresses.
  50. *
  51. * @author tvcutsem
  52. */
  53. public class MembershipNotifier extends ExtendedReceiverAdapter implements MembershipListener {
  54. /**
  55. * Members of the previously accepted view are stored to evaluate the difference with any
  56. * new view that may be signalled to this class.
  57. */
  58. private final Vector knownMembers_;
  59. /**
  60. * A collection of ConnectionListeners which are interested in the (dis)appearance of a single
  61. * node in the JGroups overlay network.
  62. */
  63. private final MultiMap connectionListeners_;
  64. /**
  65. * The general manager for service discovery for the entire virtual machine. Whenever a new VM
  66. * is encountered, this manager needs to be notified such that it can exchange the necessary
  67. * service descriptions. Likewise, VM disconnections should be delegated to this listener.
  68. */
  69. private final DiscoveryListener discoveryManager_;
  70. /**
  71. * Creates a new MembershipNotifier on which ConnectionListeners monitoring the (dis)appearance
  72. * of a single address can register to.
  73. * @param discoveryManager - the service discovery manager for the current address.
  74. */
  75. public MembershipNotifier(DiscoveryListener discoveryManager) {
  76. discoveryManager_ = discoveryManager;
  77. connectionListeners_ = new MultiMap();
  78. knownMembers_ = new Vector();
  79. }
  80. /**
  81. * Registers <code>listener</code> to be notified whenever a virtual machine becomes (un)reachable.
  82. *
  83. * TODO: store only WEAK references to the remote references
  84. *
  85. * @param virtualMachine - an address of the virtual machine hosting the object the listener is interested in
  86. * @param listener - a listener which will be notified whenever the said address connects or disconnects
  87. */
  88. public synchronized void addConnectionListener(GUID virtualMachine, ConnectionListener listener) {
  89. connectionListeners_.put(virtualMachine, listener);
  90. }
  91. /**
  92. * Unregisters <code>listener</code> such that it will no longer be notified whenever a
  93. * particular virtual machine becomes (un)reachable.
  94. */
  95. public synchronized void removeConnectionListener(GUID virtualMachine, ConnectionListener listener) {
  96. connectionListeners_.removeValue(virtualMachine, listener);
  97. }
  98. /**
  99. * This method is a callback from the JGroups framework that is invoked whenever the
  100. * set of connected group members has changed. The callback responds to such an event
  101. * by comparing the new set of members with the previously known set of members to calculate
  102. * which members joined and left. For each of these joined and left members, the corresponding
  103. * connection listeners are notified. Also, the discovery manager is always notified when
  104. * a member has joined.
  105. */
  106. public synchronized void viewAccepted(View newView) {
  107. Vector newMembers = newView.getMembers();
  108. Logging.VirtualMachine_LOG.debug("received new view: " + newView);
  109. // for each new member, check whether that new member was present in previous view
  110. for (Iterator iter = newMembers.iterator(); iter.hasNext();) {
  111. Address member = (Address) iter.next();
  112. if (!knownMembers_.contains(member)) {
  113. // member who is in new view but not in old view: joined
  114. // notify discovery manager
  115. discoveryManager_.memberJoined(member);
  116. }
  117. }
  118. // for each old member, check whether the old member is still present in new view
  119. for (Iterator iter = knownMembers_.iterator(); iter.hasNext();) {
  120. Address member = (Address) iter.next();
  121. if (!newMembers.contains(member)) {
  122. // member who is in old view but not in new view: left
  123. // notify discovery manager
  124. discoveryManager_.memberLeft(member);
  125. }
  126. }
  127. // new view becomes previous view
  128. knownMembers_.clear();
  129. knownMembers_.addAll(newMembers);
  130. }
  131. public synchronized void notifyConnected(GUID vmId){
  132. //notify all connectionlisteners for this member
  133. Set listeners = (Set)connectionListeners_.get(vmId);
  134. if(listeners != null) {
  135. for (Iterator i = listeners.iterator(); i.hasNext();) {
  136. ConnectionListener listener = (ConnectionListener) i.next();
  137. listener.connected();
  138. }
  139. }
  140. }
  141. public synchronized void notifyDisconnected(GUID vmId){
  142. //notify all connectionlisteners for this member
  143. Set listeners = (Set)connectionListeners_.get(vmId);
  144. if(listeners != null) {
  145. for (Iterator i = listeners.iterator(); i.hasNext();) {
  146. ConnectionListener listener = (ConnectionListener) i.next();
  147. listener.disconnected();
  148. }
  149. }
  150. }
  151. // Called by the VM when it has disconnected from the underlying channel
  152. public synchronized void channelDisconnected() {
  153. for (Iterator membersI = knownMembers_.iterator(); membersI.hasNext();) {
  154. // for all members who were in the view
  155. Address member = (Address) membersI.next();
  156. // notify discovery manager
  157. discoveryManager_.memberLeft(member);
  158. }
  159. // clear the set of known members
  160. knownMembers_.clear();
  161. }
  162. }