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 }