View Javadoc

1   /*
2    * Copyright (c) 1998-2002 The Jgroup Team.
3    *
4    * This program is free software; you can redistribute it and/or modify
5    * it under the terms of the GNU Lesser General Public License version 2 as
6    * published by the Free Software Foundation.
7    *
8    * This program is distributed in the hope that it will be useful,
9    * but WITHOUT ANY WARRANTY; without even the implied warranty of
10   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11   * GNU Lesser General Public License for more details.
12   *
13   * You should have received a copy of the GNU Lesser General Public License
14   * along with this program; if not, write to the Free Software
15   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16   *
17   */
18  
19  package jgroup.relacs.config;
20  
21  import java.net.InetAddress;
22  import java.net.UnknownHostException;
23  
24  import jgroup.core.ConfigurationException;
25  import jgroup.core.MemberId;
26  import jgroup.util.Network;
27  
28  import org.w3c.dom.Element;
29  import org.w3c.dom.Node;
30  import org.w3c.dom.NodeList;
31  
32  
33  /**
34   *  The <code>DistributedSystemConfig</code> object contains a
35   *  description of the distributed system on which distributed
36   *  computations can be executed.  Currently, a distributed system is
37   *  described as a collection of domains and hosts, and is read into
38   *  this object from an XML configuration file.  See the Jgroup
39   *  programmers manual for details about the format of this
40   *  configuration file.
41   *
42   *  @author Alberto Montresor
43   *  @author Hein Meling
44   *  @since Jgroup 1.2
45   */
46  public final class DistributedSystemConfig
47    implements ConfigurationObject
48  {
49  
50    ////////////////////////////////////////////////////////////////////////////////////////////
51    // Tags
52    ////////////////////////////////////////////////////////////////////////////////////////////
53  
54    private static final String DOMAIN_TAG_NAME            = "Domain";
55    private static final String HOST_TAG_NAME              = "Host";
56    private static final String NAME_ATTRIB                = "name";
57    private static final String ADDRESS_ATTRIB             = "address";
58    private static final String PORT_ATTRIB                = "port";
59    private static final String JDAEMONS_ATTRIB            = "jdaemons";
60  
61  
62    ////////////////////////////////////////////////////////////////////////////////////////////
63    // Static fields
64    ////////////////////////////////////////////////////////////////////////////////////////////
65  
66    /** Set of all hosts in this distributed system; independent of domains. */
67    private static final HostSet allHosts = new HostSet();
68  
69    /** The endpoint considered to be the local host. */
70    private static Host localHost = null;
71  
72    /** The endpoint considered to be the local domain. */
73    private static Domain localDomain = null;
74  
75  
76    ////////////////////////////////////////////////////////////////////////////////////////////
77    // Fields
78    ////////////////////////////////////////////////////////////////////////////////////////////
79  
80    /** Set of domains in this distributed system */
81    private DomainSet domains = new DomainSet();
82  
83  
84    ////////////////////////////////////////////////////////////////////////////////////////////
85    // Constructors
86    ////////////////////////////////////////////////////////////////////////////////////////////
87  
88    /**
89     *  Constructs an empty distributed system.
90     */
91    public DistributedSystemConfig()
92    {
93    }
94  
95  
96    ////////////////////////////////////////////////////////////////////////////////////////////
97    // Methods from ConfigurationObject
98    ////////////////////////////////////////////////////////////////////////////////////////////
99  
100   /**
101    *  Parses the specified element.
102    */
103   public void parse(Element elm)
104     throws ConfigurationException
105   {
106     /* Nodes within DS should be Domain tags. */
107     NodeList domainList = elm.getChildNodes();
108     
109     /* Parse the list of domains */
110     for (int i=1; i <= domainList.getLength(); i++) {
111       Node node = domainList.item(i);
112       if (node != null && !node.getNodeName().startsWith("#")) {
113         elm = (Element) node;
114         if (ConfigParser.checkTag(elm, DOMAIN_TAG_NAME)) 
115           parseDomain(elm);
116       }
117     }
118     /*
119      * If this exception is thrown, it is likely that the localhost
120      * is not configured correctly (check your local /etc/hosts file)
121      */
122     if (localHost != null && localHost.getAddress().isLoopbackAddress()) {
123       throw new ConfigurationException("Cannot use loopback as a configured server address");
124     }
125   }
126 
127 
128   ////////////////////////////////////////////////////////////////////////////////////////////
129   // Private methods for parsing
130   ////////////////////////////////////////////////////////////////////////////////////////////
131 
132   private void parseDomain(Element elm)
133     throws ConfigurationException
134   {
135     /* 
136      *  Read attributes; "-" in the domain name corresponds to empty 
137      */
138     String domainname = ConfigParser.getAttrib(elm, NAME_ATTRIB, true);
139     if ("-".equals(domainname))
140       domainname = "";
141     String address = ConfigParser.getAttrib(elm, ADDRESS_ATTRIB, true);
142     int port = ConfigParser.getIntAttrib(elm, PORT_ATTRIB, false);
143     int jdaemons = ConfigParser.getIntAttrib(elm, JDAEMONS_ATTRIB, false);
144 
145     /* Create a new domain object with the parsed information */
146     Domain domain = null;
147     try {
148       domain = new Domain(domainname, address, port, jdaemons);
149     } catch (UnknownHostException e) {
150       throw new ConfigurationException("Unknown multicast address: " + address);
151     } catch (IllegalArgumentException e) {
152       throw new ConfigurationException(e.getMessage());
153     }
154 
155     /* Add the domain to the system */
156     if (!domains.addDomain(domain))
157       throw new ConfigurationException("Multiple definitions of domain: " + domain);
158 
159     /* Nodes within the domain should be host tags. */
160     NodeList hostList = elm.getChildNodes();
161     /* Parse the list of hosts */
162     for (int i=1; i <= hostList.getLength(); i++) {
163       Node node = hostList.item(i);
164       if (node != null && !node.getNodeName().startsWith("#")) {
165         elm = (Element)node;
166         if (ConfigParser.checkTag(elm, HOST_TAG_NAME)) 
167           parseHost(domain, elm);
168       }
169     }
170   }
171 
172 
173   private void parseHost(Domain domain, Element elm)
174     throws ConfigurationException
175   {
176     String hostname = ConfigParser.getAttrib(elm, NAME_ATTRIB, true);
177     int port = ConfigParser.getIntAttrib(elm, PORT_ATTRIB, true);
178 
179     /* Create a new host object with the parsed information */
180     Host host = null;
181     try {
182       host = new Host(hostname, domain, port);
183     } catch(UnknownHostException e) {
184       throw new ConfigurationException("Unknown host: " + hostname);
185     }
186 
187     /* Add the host to this domain */
188     if (!domain.addHost(host))
189       throw new ConfigurationException("Multple definitions of host: " + host);
190 
191     /* Add the host to the all hosts set */
192     allHosts.addHost(host);
193 
194     /* Check if this host is a local host */
195     if (host.isLocal()) {
196       localHost = host;
197       localDomain = domain;
198     }
199   }
200 
201 
202   ////////////////////////////////////////////////////////////////////////////////////////////
203   // Access methods
204   ////////////////////////////////////////////////////////////////////////////////////////////
205 
206   /**
207    *  Returns the parsed set of domains.
208    */
209   public DomainSet getDomainSet()
210   {
211     return domains;
212   }
213 
214 
215   /**
216    *  Returns a set of all hosts parsed; independent of domain.
217    */
218   public HostSet getAllHosts()
219   {
220     return allHosts;
221   }
222 
223 
224   /**
225    *  Returns the size of all hosts parsed; independent of domain.
226    */
227   public int size()
228   {
229     return allHosts.size();
230   }
231 
232 
233   /**
234    *  Returns the number of domains parsed.
235    */
236   public int numOfDomains()
237   {
238     return domains.size();
239   }
240 
241 
242   ////////////////////////////////////////////////////////////////////////////////////////////
243   // Access methods - only for server side
244   ////////////////////////////////////////////////////////////////////////////////////////////
245 
246   /**
247    *  Returns the host object associated with the given member.
248    */
249   public static Host getHost(MemberId member)
250   {
251     return allHosts.getHost(member);
252   }
253 
254 
255   /**
256    *  Returns the host object associated with the given internet address.
257    */
258   public static Host getHost(InetAddress inetAdr)
259   {
260     return allHosts.getHost(inetAdr);
261   }
262 
263 
264   /**
265    *  Returns the endpoint that is considered local to this host.
266    */
267   public static Host getLocalHost()
268   {
269     return localHost;
270   }
271 
272 
273   /**
274    *  Returns the domain endpoint that is considered local to this
275    *  domain.
276    */
277   public static Domain getLocalDomain()
278   {
279     return localDomain;
280   }
281 
282 
283   /**
284    *  Returns true if the local host is specified in the distributed
285    *  system configuration; false is returned otherwise.
286    */
287   public boolean containsLocalHost()
288   {
289     return localHost != null;
290   }
291 
292 
293   /**
294    *  Set the local host and add it to the set of available hosts.
295    *  This should be used with care, and only for bootstrap purposes
296    *  since other servers will not find the local host unless it is
297    *  specified in the <code>config.xml</code> file.
298    *
299    *  Local host is not set if already defined in the configuration.
300    *
301    *  @throws UnknownHostException
302    */
303   public static void setLocalHost()
304     throws UnknownHostException
305   {
306     if (localHost == null) {
307       localDomain = new Domain(Network.getLocalDomainName());
308       localHost = new Host(Network.getLocalMachineName(), localDomain, 1991);
309       allHosts.addHost(localHost);
310       System.out.println("hosts: " + allHosts);
311     }
312   }
313 
314 
315   /**
316    *  Ping all hosts in the current configuration.  Returns true if
317    *  at least one host does not respond; i.e., the <code>ExecService</code>
318    *  is not running on one or more hosts in the system.  False indicates
319    *  that all is well.
320    */
321   public static boolean updateAll()
322   {
323     HostSet availHosts = allHosts.getAvailHosts();
324     return !availHosts.containsAll(allHosts);
325   }
326 
327 
328   ////////////////////////////////////////////////////////////////////////////////////////////
329   // Override methods in Object
330   ////////////////////////////////////////////////////////////////////////////////////////////
331 
332   public int hashCode()
333   {
334     return domains.hashCode() ^ allHosts.hashCode();
335   }
336 
337 
338   /**
339    *  Returns a string representation of this object
340    */
341   public String toString()
342   {
343     return toString(false);
344   }
345 
346   /**
347    *  Returns a string representation of this object;
348    *  
349    *  @param full If true, prints also the complete host set for each domain.
350    */
351   public String toString(boolean full)
352   {
353     StringBuilder buf = new StringBuilder();
354     buf.append("[DistributedSystemConfig:\n");
355     buf.append(domains.toString(full));
356     buf.append("]");
357     return buf.toString();
358   }
359 
360 } // END DistributedSystemConfig