/interpreter/tags/at2dist041108/src/edu/vub/at/actors/net/ConnectionListenerManager.java
Java | 175 lines | 89 code | 12 blank | 74 comment | 29 complexity | a63a093438d10d8958dc9bcd0553f668 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 */ 28package edu.vub.at.actors.net; 29 30import edu.vub.at.actors.id.ATObjectID; 31import edu.vub.at.actors.id.VirtualMachineID; 32import edu.vub.at.actors.natives.NATFarReference; 33import edu.vub.at.util.logging.Logging; 34import edu.vub.util.MultiMap; 35 36import java.lang.ref.WeakReference; 37import java.util.Iterator; 38import java.util.Set; 39 40/** 41 * An instance of this class manages disconnection and reconnection subscriptions and 42 * notifications for far references. Whenever virtual machines connect or 43 * disconnect from the multicast group, this object is notified. Its role is to propagate 44 * these notifications to all registered ConnectionListeners, which will usually be remote 45 * references pointing to objects hosted by the connecting/disconnecting VM. 46 * 47 * @author tvcutsem 48 */ 49public class ConnectionListenerManager { 50 51 /** 52 * A collection of ConnectionListeners which are interested in the (dis)appearance of a single 53 * node in the overlay network. 54 */ 55 private final MultiMap connectionListeners_; 56 57 /** 58 * Creates a new manager on which ConnectionListeners monitoring the (dis)appearance 59 * of a single address can register to. 60 */ 61 public ConnectionListenerManager() { 62 connectionListeners_ = new MultiMap(); 63 } 64 65 /** 66 * Registers <code>listener</code> to be notified whenever a virtual machine becomes (un)reachable. 67 * 68 * @param virtualMachine - an address of the virtual machine hosting the object the listener is interested in 69 * @param listener - a listener which will be notified whenever the said address connects or disconnects 70 */ 71 public synchronized void addConnectionListener(VirtualMachineID virtualMachine, ConnectionListener listener) { 72 connectionListeners_.put(virtualMachine, new WeakReference(listener)); 73 } 74 75 /** 76 * Unregisters <code>listener</code> such that it will no longer be notified whenever a 77 * particular virtual machine becomes (un)reachable. 78 */ 79 public synchronized void removeConnectionListener(VirtualMachineID virtualMachine, ConnectionListener listener) { 80 81 Set listeners = (Set)connectionListeners_.get(virtualMachine); 82 if(listeners != null) { 83 for (Iterator i = listeners.iterator(); i.hasNext();) { 84 WeakReference pooled = (WeakReference) i.next(); 85 if (pooled != null) { 86 ConnectionListener list = (ConnectionListener) pooled.get(); 87 if( list != null){ 88 if (list.equals(listener)) { 89 Logging.VirtualMachine_LOG.info("Removing ELFarReference from CLM " + this); 90 i.remove(); 91 } 92 }else{ 93 // the listener referenced by the WeakReference was already gced => remove the pointer to WeakReference. 94 i.remove(); 95 } 96 } 97 } 98 } 99 } 100 101 /** 102 * Notify all connection listeners for the given VM id that that VM has come online 103 */ 104 public synchronized void notifyConnected(VirtualMachineID vmId) { 105 //notify all connectionlisteners for this member 106 Set listeners = (Set)connectionListeners_.get(vmId); 107 if (listeners != null) { 108 for (Iterator i = listeners.iterator(); i.hasNext();) { 109 WeakReference pooled = (WeakReference) i.next(); 110 if (pooled != null) { 111 ConnectionListener listener = (ConnectionListener) pooled.get(); 112 if (listener != null){ 113 listener.connected(); 114 }else{ 115 // the listener referenced by the WeakReference was already gced => remove the pointer to WeakReference. 116 i.remove(); 117 } 118 } 119 } 120 } 121 } 122 123 /** 124 * Notify all connection listeners for the given VM id that that VM has gone offline 125 */ 126 public synchronized void notifyDisconnected(VirtualMachineID vmId){ 127 //notify all connectionlisteners for this member 128 Set listeners = (Set)connectionListeners_.get(vmId); 129 if (listeners != null) { 130 for (Iterator i = listeners.iterator(); i.hasNext();) { 131 WeakReference pooled = (WeakReference) i.next(); 132 if (pooled != null) { 133 ConnectionListener listener = (ConnectionListener) pooled.get(); 134 if (listener != null){ 135 listener.disconnected(); 136 }else{ 137 // the listener referenced by the WeakReference was already gced => remove the pointer to WeakReference. 138 i.remove(); 139 } 140 } 141 } 142 } 143 } 144 145 /** 146 * Notify all connection listeners registered on the given remote object 147 */ 148 public synchronized void notifyObjectTakenOffline(ATObjectID objId){ 149 //notify only the connectionlisteners for this objId 150 Set listeners = (Set)connectionListeners_.get(objId.getVirtualMachineId()); 151 if (listeners != null) { 152 for (Iterator i = listeners.iterator(); i.hasNext();) { 153 WeakReference pooled = (WeakReference) i.next(); 154 if (pooled != null) { 155 ConnectionListener listener = (ConnectionListener) pooled.get(); 156 if (listener instanceof NATFarReference) { 157 ATObjectID destination = ((NATFarReference)listener).getObjectId(); 158 if (destination.equals(objId)){ 159 listener.takenOffline(); 160 //The entry on the table is removed so that the remote far reference is never 161 //notified when the vmid hosting the offline object becomes (un)reachable. 162 //In fact, the reference doesn't care about the such notifications because 163 //an offline object will never become online. 164 i.remove(); 165 } 166 }else{ 167 // the listener referenced by the WeakReference was already gced => remove the pointer to WeakReference. 168 i.remove(); 169 } 170 } 171 } 172 } 173 } 174 175}