1 package org.sourceforge.jemm;
2
3 import java.io.File;
4
5 import org.apache.commons.cli.CommandLine;
6 import org.apache.commons.cli.GnuParser;
7 import org.apache.commons.cli.HelpFormatter;
8 import org.apache.commons.cli.Options;
9 import org.apache.commons.cli.ParseException;
10 import org.apache.log4j.Logger;
11 import org.sourceforge.jemm.comm.connection.ConnectionException;
12 import org.sourceforge.jemm.comm.connection.socket.SocketServerConnectionFactory;
13 import org.sourceforge.jemm.database.Database;
14 import org.sourceforge.jemm.database.memory.MemoryDatabase;
15 import org.sourceforge.jemm.database.persistent.berkeley.BDbDatabase;
16 import org.sourceforge.jemm.database.remote.server.RemoteDatabaseServer;
17 import org.sourceforge.jemm.server.ServerOptions;
18 import org.sourceforge.jemm.server.ShutdownRequestListener;
19 import org.sourceforge.jemm.server.ShutdownRequestReceiver;
20 import org.sourceforge.jemm.server.ShutdownRequestSender;
21
22
23
24
25
26
27
28
29
30 public final class JemmServer {
31
32 private static final Logger LOG = Logger.getLogger(JemmServer.class);
33
34 private static RemoteDatabaseServer remoteDatabase;
35 private static MemoryDatabase memoryDatabase;
36 private static BDbDatabase persistentDatabase;
37 private static ShutdownRequestReceiver shutdownHandler;
38
39
40 private JemmServer() {}
41
42
43 public static void main(String args[]) throws Exception {
44
45 GnuParser parser = new GnuParser();
46 Options cmdLineOptions = ServerOptions.generateOptions();
47 CommandLine cmd = parser.parse(cmdLineOptions,args);
48 if(cmd.hasOption('h')) {
49 HelpFormatter helpFormatter = new HelpFormatter();
50 helpFormatter.printHelp(80,"java org.sourceforge.jemm.JemmServer <options>", null, cmdLineOptions, null);
51 System.exit(0);
52 }
53
54 try {
55 ServerOptions options = new ServerOptions(cmd);
56 switch(options.getAction()) {
57 case START:
58 serverStart(options);
59 break;
60 case STOP:
61 serverStop(options);
62 break;
63 default:
64 throw new IllegalStateException("Action " + options.getAction() + " not handled");
65 }
66
67 } catch(ParseException pe) {
68 HelpFormatter helpFormatter = new HelpFormatter();
69 System.out.println("Error parsing command line options: " + pe.getMessage());
70 helpFormatter.printHelp(80,"java org.sourceforge.jemm.JemmServer <options>", null, cmdLineOptions, null);
71 }
72 }
73
74
75 private static void serverStop(ServerOptions options) {
76 ShutdownRequestSender.sendRequest("localhost", options.getControlPort());
77 }
78
79
80 private static void serverStart(ServerOptions options) {
81 Database db = null;
82
83 System.out.println("Running with configuration:");
84 System.out.println(options.toString());
85
86 switch(options.getMode()) {
87 case PERSISTENT:
88 File storageDir = options.getDataDir();
89 persistentDatabase = new BDbDatabase(storageDir);
90 db = persistentDatabase;
91 break;
92 case MEMORY:
93 memoryDatabase = new MemoryDatabase();
94 db = memoryDatabase;
95 break;
96 default:
97 throw new IllegalStateException("Server mode " + options.getMode() + " not handled");
98 }
99
100 shutdownHandler = new ShutdownRequestReceiver(options.getControlPort(),
101 new ShutdownRequestListener() {
102 @Override
103 public void shutdownRequest() {
104 LOG.info("Shutdown request received");
105 LOG.info("Closing client connections");
106 remoteDatabase.shutdown();
107
108 LOG.info("Waiting 2 second for client connection cleanup");
109
110 try {
111 Thread.sleep(2000);
112 } catch(InterruptedException ie) {
113 LOG.warn("Interrupted Exception received whilst waiting for shutdown",ie);
114 }
115
116 LOG.info("Closing underlying database");
117 if(memoryDatabase != null)
118 memoryDatabase.shutdown();
119 else if(persistentDatabase != null)
120 persistentDatabase.shutdown();
121
122 shutdownHandler.shutdown();
123 LOG.info("System shutdown");
124
125 }
126 });
127 shutdownHandler.start();
128
129 try {
130 remoteDatabase = new RemoteDatabaseServer(new SocketServerConnectionFactory(options.getPort()),db);
131 System.out.println("JemmServer running, listening for clients on port " + options.getPort());
132 } catch(ConnectionException ce) {
133 System.out.println("Unable to initialise database, is the port available?");
134 System.out.println("Reported error is:");
135 ce.printStackTrace();
136 System.exit(1);
137 }
138 }
139 }