001: /**
002: * com.mckoi.database.control.DBSystem 27 Mar 2002
003: *
004: * Mckoi SQL Database ( http://www.mckoi.com/database )
005: * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * Version 2 as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License Version 2 for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * Version 2 along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: * Change Log:
021: *
022: *
023: */package com.mckoi.database.control;
024:
025: import com.mckoi.database.Database;
026: import com.mckoi.database.DatabaseException;
027: import com.mckoi.database.jdbc.MConnection;
028: import com.mckoi.database.jdbc.DatabaseInterface;
029: import com.mckoi.database.jdbcserver.JDBCDatabaseInterface;
030: import com.mckoi.debug.*;
031:
032: import java.sql.Connection;
033: import java.sql.SQLException;
034:
035: /**
036: * An object used to access and control a single database system running in
037: * the current JVM. This object provides various access methods to
038: * safely manipulate the database, as well as allowing server plug-ins. For
039: * example, a TCP/IP JDBC server component might be plugged into this object
040: * to open the database to remote access.
041: *
042: * @author Tobias Downer
043: */
044:
045: public final class DBSystem {
046:
047: /**
048: * The DBController object.
049: */
050: private DBController controller;
051:
052: /**
053: * The DBConfig object that describes the startup configuration of the
054: * database.
055: */
056: private DBConfig config;
057:
058: /**
059: * The underlying Database object of this system. This object gives low
060: * level access to the system.
061: */
062: private Database database;
063:
064: /**
065: * An internal counter for internal connections created on this system.
066: */
067: private int internal_counter;
068:
069: /**
070: * Package-protected constructor.
071: */
072: DBSystem(DBController controller, DBConfig config, Database database) {
073: this .controller = controller;
074: this .config = config;
075: this .database = database;
076: this .internal_counter = 0;
077:
078: // Register the shut down delegate,
079: database.registerShutDownDelegate(new Runnable() {
080: public void run() {
081: internalDispose();
082: }
083: });
084:
085: // Enable commands to the database system...
086: database.setIsExecutingCommands(true);
087:
088: }
089:
090: /**
091: * Returns an immutable version of the database system configuration.
092: */
093: public DBConfig getConfig() {
094: return config;
095: }
096:
097: // ---------- Internal access methods ----------
098:
099: /**
100: * Returns the com.mckoi.database.Database object for this control. This
101: * methods only works correctly if the database engine has successfully been
102: * initialized.
103: * <p>
104: * This object is generally not very useful unless you intend to perform
105: * some sort of low level function on the database. This object can be
106: * used to bypass the SQL layer and talk directly with the internals of
107: * the database.
108: *
109: * @return a Database object that can be used to access the database system
110: * at a low level.
111: */
112: public Database getDatabase() {
113: return database;
114: }
115:
116: /**
117: * Makes a connection to the database and returns a java.sql.Connection
118: * object that can be used to execute queries on the database. This is a
119: * standard connection that talks directly with the database without having
120: * to go through any communication protocol layers.
121: * <p>
122: * For example, if this control is for a Mckoi database server, the
123: * java.sql.Connection returned here does not go through the TCP/IP
124: * connection. For this reason certain database configuration constraints
125: * (such as number of concurrent connection on the database) may not apply
126: * to this connection.
127: * <p>
128: * The java.sql.Connection returned here acts exactly as an object returned
129: * by a java.sql.MDriver object.
130: * <p>
131: * An SQLException is thrown if the login fails.
132: *
133: * @param schema the initial database schema to start the connection in.
134: * @param username the user to login to the database under.
135: * @param password the password of the user.
136: * @throws SQLException if authentication of the user fails.
137: * @return a JDBC java.sql.Connection used to access the database.
138: */
139: public Connection getConnection(String schema, String username,
140: String password) throws SQLException {
141:
142: // Create the host string, formatted as 'Internal/[hash number]/[counter]'
143: StringBuffer buf = new StringBuffer();
144: buf.append("Internal/");
145: buf.append(hashCode());
146: buf.append('/');
147: synchronized (this ) {
148: buf.append(internal_counter);
149: ++internal_counter;
150: }
151: String host_string = new String(buf);
152:
153: // Create the database interface for an internal database connection.
154: DatabaseInterface db_interface = new JDBCDatabaseInterface(
155: getDatabase(), host_string);
156: // Create the MConnection object (very minimal cache settings for an
157: // internal connection).
158: MConnection connection = new MConnection("", db_interface, 8,
159: 4092000);
160: // Attempt to log in with the given username and password (default schema)
161: connection.login(schema, username, password);
162:
163: // And return the new connection
164: return connection;
165: }
166:
167: /**
168: * Makes a connection to the database and returns a java.sql.Connection
169: * object that can be used to execute queries on the database. This is a
170: * standard connection that talks directly with the database without having
171: * to go through any communication protocol layers.
172: * <p>
173: * For example, if this control is for a Mckoi database server, the
174: * java.sql.Connection returned here does not go through the TCP/IP
175: * connection. For this reason certain database configuration constraints
176: * (such as number of concurrent connection on the database) may not apply
177: * to this connection.
178: * <p>
179: * The java.sql.Connection returned here acts exactly as an object returned
180: * by a java.sql.MDriver object.
181: * <p>
182: * An SQLException is thrown if the login fails.
183: *
184: * @param username the user to login to the database under.
185: * @param password the password of the user.
186: * @throws SQLException if authentication of the user fails.
187: * @return a JDBC java.sql.Connection used to access the database.
188: */
189: public Connection getConnection(String username, String password)
190: throws SQLException {
191: return getConnection(null, username, password);
192: }
193:
194: // ---------- Global methods ----------
195:
196: /**
197: * Sets a flag that causes the database to delete itself from the file system
198: * when it is shut down. This is useful if an application needs a
199: * temporary database to work with that is released from the file system
200: * when the application ends.
201: * <p>
202: * By default, a database is not deleted from the file system when it is
203: * closed.
204: * <p>
205: * <b>NOTE: Use with care - setting this flag will cause all data stored
206: * in the database to be lost when the database is shut down.</b>
207: */
208: public final void setDeleteOnClose(boolean status) {
209: database.setDeleteOnShutdown(status);
210: }
211:
212: /**
213: * Closes this database system so it is no longer able to process queries.
214: * A database may be shut down either through this method or by executing a
215: * query that shuts the system down (for example, 'SHUTDOWN').
216: * <p>
217: * When a database system is closed, it is not able to be restarted again
218: * unless a new DBSystem object is obtained from the DBController.
219: * <p>
220: * This method also disposes all resources associated with the
221: * database system (such as threads, etc) so that it may be reclaimed by
222: * the garbage collector.
223: * <p>
224: * When this method returns this object is no longer usable.
225: */
226: public void close() {
227: if (database != null) {
228: database.startShutDownThread();
229: database.waitUntilShutdown();
230: }
231: }
232:
233: // ---------- Private methods ----------
234:
235: /**
236: * Disposes of all the resources associated with this system. Note that
237: * this is private method. It may only be called from the shutdown
238: * delegate registered in the constructor.
239: */
240: private void internalDispose() {
241: if (database != null && database.isInitialized()) {
242:
243: // Disable commands (on worker threads) to the database system...
244: database.setIsExecutingCommands(false);
245:
246: try {
247: database.shutdown();
248: } catch (DatabaseException e) {
249: database
250: .Debug()
251: .write(Lvl.ERROR, this ,
252: "Unable to shutdown database because of exception");
253: database.Debug().writeException(Lvl.ERROR, e);
254: }
255: }
256: controller = null;
257: config = null;
258: database = null;
259: }
260:
261: }
|