KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mckoi > database > DatabaseSystem


1 /**
2  * com.mckoi.database.DatabaseSystem 12 Aug 2000
3  *
4  * Mckoi SQL Database ( http://www.mckoi.com/database )
5  * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * Version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License Version 2 for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * Version 2 along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * Change Log:
21  *
22  *
23  */

24
25 package com.mckoi.database;
26
27 import com.mckoi.util.Stats;
28 import com.mckoi.debug.*;
29 import com.mckoi.database.control.DBConfig;
30 //import java.io.File;
31
import java.util.List JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 //import java.util.ResourceBundle;
34
//import java.util.MissingResourceException;
35
import java.util.Properties JavaDoc;
36
37 /**
38  * This class provides information about shared resources available for the
39  * entire database system running in this VM. Shared information includes
40  * configuration details, DataCellCache, plug-ins, user management, etc.
41  *
42  * @author Tobias Downer
43  */

44
45 public final class DatabaseSystem extends TransactionSystem {
46
47   /**
48    * The StatementCache that maintains a cache of parsed queries.
49    */

50   private StatementCache statement_cache = null;
51
52   /**
53    * True if all queries on the database should be logged in the 'commands.log'
54    * file in the log directory.
55    */

56   private boolean query_logging;
57
58   /**
59    * The WorkerPool object that manages access to the database(s) in the
60    * system.
61    */

62   private WorkerPool worker_pool;
63
64   /**
65    * The list of Database objects that this system is being managed by this
66    * VM.
67    */

68   private ArrayList JavaDoc database_list;
69
70   /**
71    * Set to true when the database is shut down.
72    */

73   private boolean shutdown = false;
74
75   /**
76    * The UserManager object that handles users connected to the database
77    * engine.
78    */

79   private UserManager user_manager;
80
81   /**
82    * The thread to run to shut down the database system.
83    */

84   private ShutdownThread shutdown_thread;
85
86   /**
87    * Constructor.
88    */

89   public DatabaseSystem() {
90     super();
91   }
92
93   /**
94    * Inits the DatabaseSystem with the configuration properties of the system.
95    * This can only be called once, and should be called at database boot time.
96    */

97   public void init(DBConfig config) {
98     super.init(config);
99
100     database_list = new ArrayList JavaDoc();
101
102     // Create the user manager.
103
user_manager = new UserManager();
104
105     if (config != null) {
106
107       boolean status;
108
109       // Set up the statement cache.
110
status = getConfigBoolean("statement_cache", true);
111       if (status) {
112         statement_cache = new StatementCache(this, 127, 140, 20);
113       }
114       Debug().write(Lvl.MESSAGE, DatabaseSystem.class,
115                     "statement_cache = " + status);
116
117       // The maximum number of worker threads.
118
int max_worker_threads = getConfigInt("maximum_worker_threads", 4);
119       if (max_worker_threads <= 0) {
120         max_worker_threads = 1;
121       }
122       Debug().write(Lvl.MESSAGE, DatabaseSystem.class,
123                     "Max worker threads set to: " + max_worker_threads);
124       worker_pool = new WorkerPool(this, max_worker_threads);
125
126       // Should we be logging commands?
127
query_logging = getConfigBoolean("query_logging", false);
128
129     }
130     else {
131       throw new Error JavaDoc("Config bundle already set.");
132     }
133
134     shutdown = false;
135
136   }
137
138
139
140
141   // ---------- Queries ----------
142

143   /**
144    * If query logging is enabled (all queries are output to 'commands.log' in
145    * the log directory), this returns true. Otherwise it returns false.
146    */

147   public boolean logQueries() {
148     return query_logging;
149   }
150
151
152
153
154   // ---------- Clean up ----------
155

156   /**
157    * Disposes all the resources associated with this DatabaseSystem and
158    * invalidates this object.
159    */

160   public void dispose() {
161     super.dispose();
162     worker_pool = null;
163     database_list = null;
164     user_manager = null;
165   }
166
167   // ---------- Cache Methods ----------
168

169   /**
170    * Returns the StatementCache that is used to cache StatementTree objects
171    * that are being queried by the database. This is used to reduce the
172    * SQL command parsing overhead.
173    * <p>
174    * If this method returns 'null' then statement caching is disabled.
175    */

176   public StatementCache getStatementCache() {
177     return statement_cache;
178   }
179
180
181
182
183   // ---------- System preparers ----------
184

185   /**
186    * Given a Transaction.CheckExpression, this will prepare the expression and
187    * return a new prepared CheckExpression.
188    * <p>
189    * A DatabaseSystem resolves the variables (ignoring case if necessary) and
190    * the functions of the expression.
191    */

192   public Transaction.CheckExpression prepareTransactionCheckConstraint(
193                   DataTableDef table_def, Transaction.CheckExpression check) {
194
195     return super.prepareTransactionCheckConstraint(table_def, check);
196
197   }
198
199
200   // ---------- User management ----------
201

202   /**
203    * Returns the UserManager object that handles users that are connected
204    * to the database. The aim of this class is to unify the way users are
205    * handled by the engine. It allows us to perform queries to see who's
206    * connected, and any inter-user communication (triggers).
207    */

208   UserManager getUserManager() {
209     return user_manager;
210   }
211
212   // ---------- Worker Pool Methods ----------
213

214   /**
215    * Waits until all executing commands have stopped. This is best called
216    * right after a call to 'setIsExecutingCommands(false)'. If these two
217    * commands are run, the database is in a known state where no commands
218    * can be executed.
219    * <p>
220    * NOTE: This can't be called from the WorkerThread. Deadlock will
221    * result if we were allowed to do this.
222    */

223   void waitUntilAllWorkersQuiet() {
224     worker_pool.waitUntilAllWorkersQuiet();
225   }
226
227   /**
228    * Controls whether the database system is allowed to execute commands or
229    * not. If this is set to true, then calls to 'execute' will be executed
230    * as soon as there is a free worker thread available. Otherwise no
231    * commands are executed until this is enabled.
232    */

233   void setIsExecutingCommands(boolean status) {
234     worker_pool.setIsExecutingCommands(status);
235   }
236
237   /**
238    * Executes database functions from the 'run' method of the given runnable
239    * instance on the first available worker thread. All database functions
240    * must go through a worker thread. If we ensure this, we can easily stop
241    * all database functions from executing if need be. Also, we only need to
242    * have a certain number of threads active at any one time rather than a
243    * unique thread for each connection.
244    */

245   void execute(User user, DatabaseConnection database,
246                Runnable JavaDoc runner) {
247     worker_pool.execute(user, database, runner);
248   }
249
250   // ---------- Shut down methods ----------
251

252   private final ArrayList JavaDoc shut_down_delegates = new ArrayList JavaDoc();
253
254   /**
255    * Registers the delegate that is executed when the shutdown thread
256    * is activated. Only one delegate may be registered with the database
257    * system. This is only called once and shuts down the relevant
258    * database services.
259    */

260   void registerShutDownDelegate(Runnable JavaDoc delegate) {
261     shut_down_delegates.add(delegate);
262   }
263
264   /**
265    * The shut down thread. Started when 'shutDown' is called.
266    */

267   private class ShutdownThread extends Thread JavaDoc {
268
269     private boolean finished = false;
270
271     synchronized void waitTillFinished() {
272       while (finished == false) {
273         try {
274           wait();
275         }
276         catch (InterruptedException JavaDoc e) {}
277       }
278     }
279
280     public void run() {
281       synchronized (this) {
282         if (finished) {
283           return;
284         }
285       }
286
287       // We need this pause so that the command that executed this shutdown
288
// has time to exit and retrieve the single row result.
289
try {
290         Thread.sleep(1500);
291       }
292       catch (InterruptedException JavaDoc e) {}
293       // Stops commands from being executed by the system...
294
setIsExecutingCommands(false);
295       // Wait until the worker threads are all quiet...
296
waitUntilAllWorkersQuiet();
297
298       // Close the worker pool
299
worker_pool.shutdown();
300
301       int sz = shut_down_delegates.size();
302       if (sz == 0) {
303         Debug().write(Lvl.WARNING, this, "No shut down delegates registered!");
304       }
305       else {
306         for (int i = 0; i < sz; ++i) {
307           Runnable JavaDoc shut_down_delegate = (Runnable JavaDoc) shut_down_delegates.get(i);
308           // Run the shut down delegates
309
shut_down_delegate.run();
310         }
311         shut_down_delegates.clear();
312       }
313
314       synchronized (this) {
315         // Wipe all variables from this object
316
dispose();
317
318         finished = true;
319         notifyAll();
320       }
321     }
322   };
323
324   /**
325    * This starts the ShutDown thread that is used to shut down the database
326    * server. Since the actual shutdown method is dependent on the type of
327    * database we are running (server or stand-alone) we delegate the
328    * shutdown method to the registered shutdown delegate.
329    */

330   void startShutDownThread() {
331     if (!shutdown) {
332       shutdown = true;
333       shutdown_thread = new ShutdownThread();
334       shutdown_thread.start();
335     }
336   }
337
338   /**
339    * Returns true if 'shutDown' method has been called.
340    */

341   boolean hasShutDown() {
342     return shutdown;
343   }
344
345   /**
346    * Wait until the shutdown thread has completed. (Shutdown process
347    * has finished).
348    */

349   void waitUntilShutdown() {
350     shutdown_thread.waitTillFinished();
351   }
352
353 }
354
Popular Tags