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