001: // You can redistribute this software and/or modify it under the terms of
002: // the Ozone Core License version 1 published by ozone-db.org.
003: //
004: // The original code and portions created by SMB are
005: // Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
006: //
007: // $Id: Server.java,v 1.4 2002/06/08 00:49:38 mediumnet Exp $
008:
009: package org.ozoneDB.core;
010:
011: import java.lang.reflect.*;
012: import java.io.*;
013: import org.ozoneDB.DxLib.*;
014: import org.ozoneDB.*;
015: import org.ozoneDB.util.*;
016: import org.ozoneDB.tools.*;
017:
018: /**
019: * Main class to start the stand-alone server.
020: *
021: * @author <a href="http://www.softwarebuero.de/">SMB</a>
022: * @version $Revision: 1.4 $Date: 2002/06/08 00:49:38 $
023: */
024: public class Server {
025:
026: public static Env env;
027:
028: public static boolean stop;
029:
030: public static boolean stopped;
031:
032: public static void main(String[] args) throws Exception {
033: String dir = File.separator + "tmp" + File.separator + "db";
034: String debugLevel = null;
035: boolean help = false;
036: boolean verbose = false;
037: boolean createDB = false;
038: DxArrayBag users = new DxArrayBag();
039:
040: System.out.println("ozone server - version " + Env.VERSION);
041:
042: for (int i = 0; i < args.length; i++) {
043: if (args[i].startsWith("-debug")) {
044: debugLevel = args[i].substring("-debug".length());
045: } else if (args[i].startsWith("-d")) {
046: dir = args[i].substring(2);
047: } else if (args[i].startsWith("-c")) {
048: createDB = true;
049: } else if (args[i].startsWith("-u")) {
050: String name = args[i].substring(2);
051: users.add(name);
052: } else if (args[i].startsWith("-h")) {
053: help = true;
054: } else {
055: System.out.println("illegal option: " + args[i]);
056: help = true;
057: }
058: }
059:
060: if (args.length == 0 || help) {
061: System.out
062: .println("usage: ozone -d<dir> [-h] [-debug] [-v]");
063: System.out
064: .println(" -d<directory> database directory");
065: System.out
066: .println(" -debug<level> debug level, levels are one of the string constants in the OzoneDebugLevel class");
067: System.out
068: .println(" -v starts the ozonometer (broken)");
069: System.out
070: .println(" -c create a database if neccessary");
071: System.out
072: .println(" -u<name> add user <name>");
073: System.out
074: .println(" -h shows this help");
075: System.exit(0);
076: }
077:
078: try {
079: if (createDB) {
080:
081: // Check if a DB exists and make a new database if not.
082: if (!Install.dbExists(dir)) {
083: System.out.println("Installing new database in "
084: + dir + "...");
085:
086: Setup defaults = new Setup(null);
087: defaults.addProperties(System.getProperties(),
088: "ozoneDB.");
089: Install.createDB(dir, defaults, new PrintWriter(
090: System.out, true));
091:
092: System.out.println("Edit " + dir + Env.CONFIG_FILE
093: + " to change settings.");
094: System.out.println("install complete\n");
095: }
096: }
097:
098: System.out.println("initializing environment...");
099: env = new Env(dir, debugLevel);
100:
101: // This is a good place to set up our shutdown hook. Doing it
102: // earlier would case a NullPointerException in race conditions.
103: // Doing it now is fine in terms of preventing database corruption
104: // because request processing has no yet begun.
105: setupShutdownHook();
106:
107: int freeSlot = 101;
108: for (int i = 0; i < users.count(); i++) {
109: String name = (String) users.elementAtIndex(i);
110: // don't insert a name twice
111: if (env.userManager.userForName(name) != null) {
112: env.logWriter.newEntry(env, "User " + name
113: + " already exists.", LogWriter.INFO);
114: continue;
115: }
116: // find a free id
117: while (env.userManager.userForID(freeSlot) != null) {
118: freeSlot++;
119: }
120: // add the user
121: env.userManager.newUser(name, freeSlot);
122: env.logWriter.newEntry(env, "user added: " + name
123: + " ID: " + freeSlot, LogWriter.INFO);
124: }
125: env.storeSetup();
126:
127: env.startExternalEventProcessing();
128: env.startDeadlockRecognition();
129:
130: System.out
131: .println("(Ctrl-C or 'q' to shutdown without admin tool)");
132:
133: InputStreamReader is = new InputStreamReader(System.in);
134: Thread.currentThread().setPriority(
135: Env.SERVER_THREAD_PRIORITY);
136:
137: stop = false;
138: stopped = false;
139: // the main loop
140: while (!stop) {
141: int gcCount = 0;
142: int stateCount = 0;
143: while (!is.ready() && !env.shuttingdown && !stop) {
144: final int sleepMillis = 250;
145:
146: // this forces also task switches
147: Thread.currentThread().sleep(sleepMillis);
148:
149: // check component states every 5sec; this is not really a
150: // good solution but it works for now
151: // if (stateCount++ >= (5000/sleepMillis)) {
152: // stateCount = 0;
153: // if (env.isComponentStateChanged()) {
154: // env.logWriter.newEntry( env, "storing server state...", LogWriter.DEBUG );
155: // env.storeSetup();
156: // }
157: // }
158:
159: // force GC
160: if (env.transactionManager.taTableCount() == 0) {
161: gcCount++;
162: } else {
163: gcCount = 0;
164: }
165: if (gcCount >= (10000 / sleepMillis)) {
166: // env.logWriter.newEntry( env, "forcing GC...", LogWriter.DEBUG3 );
167: System.gc();
168: gcCount = 0;
169: }
170: }
171:
172: if (is.ready()) {
173: int c = is.read();
174: if (c == 'q') {
175: stop = true;
176: }
177: }
178: }
179: // wait for the admin thread to deconnect
180: Thread.sleep(1000);
181:
182: // shutdown the system
183: env.shutdown();
184: stopped = true;
185: } catch (Exception e) {
186: if (env != null) {
187: env.shutdown();
188: }
189: // env.logWriter.newEntry (null, "", e, LogWriter.ERROR);
190: System.out.println("Unable to initialize server.");
191: e.printStackTrace();
192: }
193: System.exit(1);
194: }
195:
196: /**
197: * Attempt to add the shutdown hook using reflection.
198: */
199: private static void setupShutdownHook() {
200: try {
201: // We will now attempt to add the shutdown hook
202: // using reflection. If we're running in a VM that does
203: // not support shutdown hooks (i.e., pre-1.3), it will yield
204: // a NoSuchMethodException, which we quietly ignore.
205: Class runtimeClass = Runtime.class;
206: Method hookMethod = runtimeClass.getMethod(
207: "addShutdownHook", new Class[] { Thread.class });
208: Runtime rt = Runtime.getRuntime();
209: hookMethod
210: .invoke(rt, new Object[] { createShutdownHook() });
211:
212: env.logWriter
213: .newEntry(Server.class,
214: "Shutdown hook successfully added.",
215: LogWriter.INFO);
216: } catch (NoSuchMethodException nsme) {
217: /* Pre-1.3 VM. */
218: env.logWriter.newEntry(Server.class,
219: "Running on pre-1.3 VM; no shutdown hook added.",
220: LogWriter.INFO);
221: } catch (SecurityException se) {
222: /* Either a screwy setup, or permission deliberately denied. */
223: env.logWriter.newEntry(Server.class,
224: "Shutdown hook not added; permission denied.",
225: LogWriter.WARN);
226: } catch (InvocationTargetException ite) {
227: /* Runtime.addShutdownHook() failed */
228: Throwable te = ite.getTargetException();
229: env.logWriter.newEntry(Server.class,
230: "WARNING: Shutdown hook addition failed: "
231: + te.getClass().getName() + ": "
232: + te.getMessage(), LogWriter.ERROR);
233: } catch (IllegalAccessException iae) {
234: /* The VM is FUBAR. */
235: env.logWriter.newEntry(Server.class,
236: "Runtime.addShutdownHook() not public? VM bug?",
237: LogWriter.ERROR);
238: }
239: }
240:
241: /**
242: * Constructs and returns a Thread to be used as a shutdown hook.
243: */
244: private static Runnable createShutdownHook() {
245: return new Thread() {
246: public void run() {
247: if (env.shuttingdown == false) {
248: env.logWriter.newEntry(Server.class,
249: "Shutdown hook...", LogWriter.INFO);
250: try {
251: // signal the main loop to stop
252: stop = true;
253:
254: // wait for the mail thread to finish shutdown
255: while (!stopped) {
256: sleep(500);
257: }
258: } catch (Exception e) {
259: }
260: env.logWriter.newEntry(Server.class,
261: "Shutdown hook... shutdown finished.",
262: LogWriter.INFO);
263: }
264: }
265: };
266: }
267: }
|