001         package com.croftsoft.apps.vaft.core;
002    
003         import java.io.*;
004         import java.rmi.*;
005         import java.util.*;
006    
007         import com.croftsoft.apps.vaft.util.broadcast.*;
008    
009         /*********************************************************************
010         * <P>
011         * @author
012         *   <A HREF="http://www.alumni.caltech.edu/~croft">David W. Croft</A>
013         * @version
014         *   1998-04-26
015         *********************************************************************/
016    
017         public class  HostList
018           implements Cloneable, Runnable, Serializable, Broadcaster
019         //////////////////////////////////////////////////////////////////////
020         //////////////////////////////////////////////////////////////////////
021         {
022    
023         public static final String   BROADCAST_NAME = "HostList";
024    
025         private transient HostInfo   self;
026         private transient HostInfo   seed;
027         private transient long       swap_delay;
028         private transient boolean    running = false;
029         private transient Broadcast  broadcast;
030    
031         private Vector               v;
032    
033         //////////////////////////////////////////////////////////////////////
034         // Constructor method
035         //////////////////////////////////////////////////////////////////////
036    
037         public  HostList ( HostInfo  self, HostInfo  seed, long  swap_delay )
038         //////////////////////////////////////////////////////////////////////
039         {
040           this.self       = self;
041           this.seed       = seed;
042           this.swap_delay = swap_delay;
043    
044           if ( self != null )
045           {
046             try { self.convertLocalHostToAddress ( ); }
047             catch ( java.net.UnknownHostException  uhex ) { }
048           }
049           if ( seed != null )
050           {
051             try { seed.convertLocalHostToAddress ( ); }
052             catch ( java.net.UnknownHostException  uhex ) { }
053           }
054    
055           v = new Vector ( );
056           if ( self != null ) v.addElement ( self );
057           if ( seed != null ) v.addElement ( seed );
058    
059           broadcast = new Broadcast ( this );
060         }
061    
062         //////////////////////////////////////////////////////////////////////
063         // Access methods
064         //////////////////////////////////////////////////////////////////////
065    
066         public boolean  getRunning ( )
067           { return running; }
068    
069         public void     setRunning ( boolean  running )
070           { this.running = running; }
071    
072         public HostInfo  getHostInfoSelf ( ) { return self; }
073         public HostInfo  getHostInfoSeed ( ) { return seed; }
074    
075         /*********************************************************************
076         * Returns a shallow clone.
077         *********************************************************************/
078         public Vector  getHostInfoList ( ) { return ( Vector ) v.clone ( ); }
079    
080         //////////////////////////////////////////////////////////////////////
081         // Public instance methods
082         //////////////////////////////////////////////////////////////////////
083    
084         public synchronized HostList  swap ( HostList  hostList )
085         //////////////////////////////////////////////////////////////////////
086         {
087           broadcast ( "swapping HostList with remote Host..." );
088           if ( hostList == null ) return this;
089           merge ( hostList );
090    
091           // Give the peers that it does not know about.
092           Enumeration  e = v.elements ( );
093           HostList  c = null;
094           while ( e.hasMoreElements ( ) )
095           {
096             HostInfo  hostInfo = ( HostInfo ) e.nextElement ( );
097             try
098             {
099               if ( !hostList.isKnown ( hostInfo ) )
100               {
101                 if ( c == null )
102                 {
103                   c = new HostList ( hostInfo, null, swap_delay );
104                 }
105                 else c.v.addElement ( hostInfo );
106               }
107             }
108             catch ( java.net.UnknownHostException  uhex ) { }
109           }
110           return c;
111         }
112    
113         public void  run ( )
114         //////////////////////////////////////////////////////////////////////
115         {
116           running = true;
117           while ( running )
118           {
119             broadcast ( "Periodic swap begins at " + new Date ( ) );
120             swap ( );
121             broadcast ( "Periodic swap ends at " + new Date ( ) );
122             broadcast ( "Next periodic swap in "
123               + swap_delay + " milliseconds" );
124             try { Thread.currentThread ( ).sleep ( swap_delay ); }
125             catch ( InterruptedException  ex )
126             {
127               broadcast ( "Sleep interrupted" );
128             }
129           }
130           broadcast ( "Exiting swap loop" );
131         }
132    
133         public Object  clone ( )
134         //////////////////////////////////////////////////////////////////////
135         {
136           return clone ( );
137         }
138    
139         //////////////////////////////////////////////////////////////////////
140         // Private instance methods
141         //////////////////////////////////////////////////////////////////////
142    
143         /*********************************************************************
144         * Contact each remote Host and swap HostLists.
145         * Remove those Hosts which do not respond properly from my HostList.
146         *********************************************************************/
147         public synchronized void  swap ( )
148         //////////////////////////////////////////////////////////////////////
149         {
150           Vector  c = getHostInfoList ( );
151           if ( c.size ( ) < 2 )
152           {
153             try
154             {
155               if ( !isKnown ( seed ) ) c.addElement ( seed );
156             }
157             catch ( java.net.UnknownHostException  uhex ) { }
158           }
159           Enumeration  e = c.elements ( );
160           while ( e.hasMoreElements ( ) )
161           {
162             HostInfo  hostInfo = ( HostInfo ) e.nextElement ( );
163             if ( hostInfo == self ) continue;
164             try
165             {
166               broadcast ( "Attempting to swap HostLists with "
167                 + hostInfo + "." );
168               merge ( hostInfo.swap ( this ) );
169             }
170             catch ( ConnectException  cex )
171             {
172               v.removeElement ( hostInfo );
173             }
174             catch ( Exception  ex )
175             {
176    //         ex.printStackTrace ( );
177               v.removeElement ( hostInfo );
178             }
179           }
180         }
181    
182         /*********************************************************************
183         * Get the peers that I do not already know about.
184         *********************************************************************/
185         private synchronized void  merge ( HostList  hostList )
186         //////////////////////////////////////////////////////////////////////
187         {
188           if ( hostList == null ) return;
189           Enumeration  e = hostList.v.elements ( );
190           while ( e.hasMoreElements ( ) )
191           {
192             HostInfo  hostInfo = ( HostInfo ) e.nextElement ( );
193             if ( hostInfo.getRmi_server_name ( ).toLowerCase ( ).equals (
194               "localhost" ) ) continue;
195             try
196             {
197               if ( !isKnown ( hostInfo ) ) v.addElement ( hostInfo );
198             }
199             catch ( java.net.UnknownHostException  uhex ) { }
200           }
201         }
202    
203         public synchronized boolean  isKnown ( HostInfo  hostInfo )
204           throws java.net.UnknownHostException
205         //////////////////////////////////////////////////////////////////////
206         {
207           Enumeration  e = v.elements ( );
208           while ( e.hasMoreElements ( ) )
209           {
210             if ( hostInfo.matches ( ( HostInfo ) e.nextElement ( ) ) )
211               return true;
212           }
213           return false;
214         }
215    
216         //////////////////////////////////////////////////////////////////////
217         // Broacaster interface methods
218         //////////////////////////////////////////////////////////////////////
219    
220         public String  getBroadcastName ( ) { return BROADCAST_NAME; }
221    
222         public boolean  addBroadcastListener (
223           BroadcastListener  broadcastListener )
224         //////////////////////////////////////////////////////////////////////
225         {
226           return broadcast.addBroadcastListener ( broadcastListener );
227         }
228    
229         public boolean  removeBroadcastListener (
230           BroadcastListener  broadcastListener )
231         //////////////////////////////////////////////////////////////////////
232         {
233           return broadcast.removeBroadcastListener ( broadcastListener );
234         }
235    
236         public void  broadcast ( String  s )
237         //////////////////////////////////////////////////////////////////////
238         {
239           broadcast.broadcast ( s );
240         }
241    
242         //////////////////////////////////////////////////////////////////////
243         //////////////////////////////////////////////////////////////////////
244         }