Source code: org/openmosix/daemon/OpenMosixInfoServer.java
1 /*
2 * openMosixApplet is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU General Public License as published by the Free
4 * Software Foundation; either version 2, or (at your option) any later
5 * version.
6 *
7 * openMosixApplet is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10 * for more details.
11 *
12 * You should have received a copy of the GNU General Public License with
13 * this source package as the file COPYING. If not, write to
14 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
15 * Boston, MA 02111-1307, USA.
16 */
17
18 package org.openmosix.daemon;
19
20 import java.io.*;
21 import java.net.*;
22
23 /**
24 * Contains the main code: creates connections (instances of ConnHandler)
25 * with the clients.
26 * This class is able to manage several connections at the same time.
27 *
28 * @author The openMosix Applet Team
29 * @version $Id: OpenMosixInfoServer.java,v 1.9 2003/01/27 15:43:39 rejected Exp $
30 */
31 public class OpenMosixInfoServer
32 {
33 // SOFTWARE RELEASE INFO
34
35 /** software release info: major number */
36 public static final String MAJOR = "0";
37 /** software release info: minor number */
38 public static final String MINOR = "1";
39 /** software release info: build number */
40 public static final String BUILD = "0";
41 /** software release info: release info */
42 public static final String RELEASE = "beta1";
43
44 // DIRS AND FILES CONSTANTS
45
46 /** if this dir doesn't exist, we are not on an openMosix node! */
47 public static final String HPC_DIR = "/proc/hpc";
48
49 /** this directory should hold a further dir for each node in the
50 * cluster
51 */
52 public static final String HPC_NODES_DIR = "/proc/hpc/nodes";
53
54 // NETWORK STUFF
55
56 /** the default server port: 7977
57 * (in ASCII Table char 79 is 'O' and char 77 is 'M')
58 */
59 public static final int DEFAULT_SERVER_PORT=7977;
60 /** the port the server is listening on
61 */
62 private static int serverPort=DEFAULT_SERVER_PORT;
63 /** the default socket timeout in milliseconds: 60000 (60 seconds) */
64 public static final int DEFAULT_SOCKET_TIMEOUT=60000;
65 /** default socket timeout, in milliseconds */
66 private static int socketTimeout=DEFAULT_SOCKET_TIMEOUT;
67
68 /** standard exit code for succesful execution */
69 public static final int EXIT_SUCCESS = 0;
70 /** standard exit code for execution error */
71 public static final int EXIT_FAILURE = 1;
72
73 /** number of nodes to simulate in debug mode */
74 private static int debugMode = 0;
75 /** are we in daemon mode? */
76 private static boolean daemonMode = false;
77 /** Should we return float values? */
78 private static boolean returnFloatValues = false;
79
80 /** class-wide logger instance */
81 private static Logger logger=null;
82
83 /**
84 * Here starts the whole program.
85 * @param args contains all the command line options specified by the user
86 * (this variable is filled by Java at runtime)
87 */
88 public static void main(String[] args)
89 {
90 logger=Logger.getDefault();
91
92 try
93 {
94 long connectionCounter = 1;
95 checkCommandLineValues(args);
96
97 logger.log(Logger.MSGTYPE_INFO,
98 "Welcome to the OpenMosixInfoServer");
99 logger.log(Logger.MSGTYPE_INFO, "listening on port: " + serverPort);
100 logger.log(Logger.MSGTYPE_INFO, "socket timeout set to: "
101 + socketTimeout);
102
103 if (debugMode == 0) verifyIfOpenMosixIsActive();
104
105 //create the ServerSocket
106 ServerSocket s = new ServerSocket(serverPort);
107
108 while (true) //repeat forever... :)
109 {
110 // create a new socket in order to receive a client connection
111 Socket incoming = s.accept();
112 String clientIP = incoming.getInetAddress().getHostAddress();
113
114 logger.log(Logger.MSGTYPE_INFO, "starting connection #"
115 +connectionCounter+". (Client IP:"+clientIP+")");
116 // create a new handler to manage the new client connection
117 ConnHandler newConnection = new ConnHandler(incoming,
118 connectionCounter);
119 newConnection.doStart();
120 connectionCounter++;
121 }
122 }
123 catch (BindException be)
124 {
125 logger.log(Logger.MSGTYPE_ERR, "another program is currently "
126 +"listening on this port! (fatal exception!)");
127 System.err.println("port already in use: "+be.getMessage());
128 System.exit(EXIT_FAILURE);
129 }
130 catch (Exception fe) //on any other error
131 {
132 logger.log(Logger.MSGTYPE_ERR, "exception occurred in the "
133 +"connection manager (fatal exception!)");
134 fe.printStackTrace();
135 System.exit(EXIT_FAILURE);
136 }
137 }
138
139 // STUPID GETTER METHODS
140
141 /** Returns the socket timeout value expressed in milliseconds
142 * @return the socket timeout value expressed in milliseconds
143 */
144 public static int getSocketTimeout()
145 {
146 return socketTimeout;
147 }
148
149 /** Returns the server port number
150 * @return the server port number
151 */
152 public static int getServerPort()
153 {
154 return serverPort;
155 }
156
157 /** Returns the number of nodes to simulate in debug mode
158 * @return the number of nodes to simulate in debug mode
159 */
160 public static int getDebugMode()
161 {
162 return debugMode;
163 }
164
165 /** Asks whether we are in daemon mode
166 * @return true or false :)
167 */
168 public static boolean getDaemonMode()
169 {
170 return daemonMode;
171 }
172
173 /** Asks whether we should provide the client with floating point
174 * number values
175 * @return true or false :)
176 */
177 public static boolean returnFloatValues()
178 {
179 return returnFloatValues;
180 }
181
182
183 // UTILITIES
184
185 /**
186 * Verifies if openMosix is active (checks if /proc/hpc interface is active,
187 * ie: nodes directories are present).
188 * If openMosix is not active, forces program exit.
189 * This method won't be called if global DEBUG_MODE variable is set to true.
190 */
191 public static void verifyIfOpenMosixIsActive()
192 {
193 File hpcdir=new File(HPC_DIR);
194 if (! hpcdir.isDirectory())
195 {
196 logger.log(Logger.MSGTYPE_ERR, "openMosix is not active! Exiting...");
197 System.exit(EXIT_FAILURE);
198 }
199 // move to HPC_NODES_DIR (a file pointer is set to this directory)
200 File path = new File(HPC_NODES_DIR);
201 // now nodesArray should contain all of the nodes' numbers
202 String[] nodesArray = path.list();
203 if (nodesArray.length==0)
204 {
205 logger.log(Logger.MSGTYPE_ERR, "openMosix is not active! Exit forced...");
206 System.exit(EXIT_FAILURE);
207 }
208 }
209
210
211 //COMMAND LINE STUFF
212
213 /**
214 * Checks if command line options (entered by the user) are valid
215 * program options.
216 * @param argv[] is an array of strings containing all command line
217 * options (entered by the user). This variable will be set as a
218 * reference to main()'s args[] variable.
219 */
220 public static void checkCommandLineValues(String[] argv)
221 {
222 /* well, we have to check the command line arguments
223 * in a certain order because we have to know which is
224 * the logfile before we start outputting messages for
225 * instance so this is the reason for this cpu clock
226 * cycles whore :)
227 */
228
229 boolean overwriteLogfile=false;
230
231 CLIUtils cu=new CLIUtils(argv);
232
233 // these show* methods exit automatically with a succesful status
234 if (cu.checkBool("-a","--author")) CLIUtils.showAuthor();
235 if (cu.checkBool("-l","--license")) CLIUtils.showLicense();
236 if (cu.checkBool("-h","--help")) CLIUtils.showUsage();
237 if (cu.checkBool("-V","--version")) CLIUtils.showSwVersion();
238
239 if (cu.checkBool("-r","--overwrite-log-file")) overwriteLogfile=true;
240
241 if (cu.checkBool("-v","--verbose"))
242 {
243 logger.setVerboseMode(true);
244 logger.log(Logger.MSGTYPE_INFO, "verbose mode set");
245 }
246
247 if (cu.checkBool("-o","--log-file"))
248 {
249 String logFilePath=cu.checkString("-o","--log-file");
250 if (logFilePath != null && logFilePath.length() > 0)
251 {
252 try
253 {
254 logger.setLogFile(new File(logFilePath));
255 }
256 catch (IOException ex)
257 {
258 logger.log(Logger.MSGTYPE_WARN, "sorry, could not use file "
259 +logFilePath);
260 logger.log(Logger.MSGTYPE_WARN, ex.getMessage());
261 }
262 }
263 if (! logger.isLogFileSet())
264 {
265 logger.log(Logger.MSGTYPE_INFO, "falling back to the "
266 +"default log file... ");
267 try
268 {
269 logger.useDefaultLogFile();
270 logFilePath=logger.getLogFilePath();
271 logger.log(Logger.MSGTYPE_INFO, "fall back was ok");
272 }
273 catch (IOException ex)
274 {
275 logger.log(Logger.MSGTYPE_ERR, "sorry, fallback didn't "
276 +"work either");
277 ex.printStackTrace();
278 System.exit(EXIT_FAILURE);
279 }
280 }
281
282 if (overwriteLogfile)
283 {
284 try
285 {
286 logger.resetLogFile();
287 logger.log(Logger.MSGTYPE_INFO, "log file overwritten");
288 }
289 catch (IOException ex)
290 {
291 System.err.println("could not overwrite log file");
292 ex.printStackTrace();
293 System.exit(EXIT_FAILURE);
294 }
295 }
296 logger.log(Logger.MSGTYPE_INFO, "log file option was set");
297 logger.log(Logger.MSGTYPE_INFO, "appending to file: ["
298 +logger.getLogFilePath()+"]");
299 }
300
301 if (cu.checkBool("-d","--debug"))
302 {
303 try
304 {
305 debugMode=cu.checkInt("-d","--debug");
306 }
307 catch (NumberFormatException ex)
308 {
309 debugMode=5;
310 logger.log(Logger.MSGTYPE_WARN, "error parsing the --debug "
311 +"option, will use the default value: "+debugMode+" nodes");
312 }
313 logger.setDebugMode(true);
314 logger.log(Logger.MSGTYPE_INFO, "debug mode set");
315 logger.log(Logger.MSGTYPE_DEBUG, "simulating ["+debugMode
316 +"] active nodes");
317 }
318
319 if (cu.checkBool("-D","--daemon"))
320 {
321 daemonMode = true;
322 logger.log(Logger.MSGTYPE_INFO, "daemon mode set");
323 }
324
325 if (cu.checkBool("-f","--return-float-values"))
326 {
327 logger.log(Logger.MSGTYPE_INFO, "program will return float "
328 +"values instead of integers");
329 returnFloatValues = true;
330 }
331
332 if (cu.checkBool("-p","--port"))
333 {
334 int srvPort;
335
336 try
337 {
338 srvPort=cu.checkInt("-p", "--port");
339 }
340 catch (NumberFormatException ex)
341 {
342 srvPort=DEFAULT_SERVER_PORT;
343 logger.log(Logger.MSGTYPE_WARN, "error parsing the port value: "
344 +"will use the default value of "+srvPort);
345 }
346 serverPort=srvPort;
347 }
348
349 if (cu.checkBool("-s","--socket-timeout"))
350 {
351 int sktTimeOut;
352
353 try
354 {
355 sktTimeOut=cu.checkInt("-s","--socket-timeout");
356 }
357 catch (NumberFormatException ex)
358 {
359 sktTimeOut=DEFAULT_SOCKET_TIMEOUT;
360 logger.log(Logger.MSGTYPE_WARN, "error parsing the socket "
361 +" time out value: "
362 +"will use the default value of "+sktTimeOut);
363 }
364 socketTimeout=sktTimeOut;
365 }
366 }
367 }