PageRenderTime 26ms CodeModel.GetById 10ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/interpreter/tags/at2dist160410/src/edu/vub/at/actors/net/ConnectionListenerManager.java

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