| |
Mckoi SQL Database | License: | GNU General Public License (GPL) | URL: | http://mckoi.com/database/ | Description: | Mckoi SQL Database is optimized to run as a client/server database server for multiple clients |
Package Name | Comment | com.mckoi |
com.mckoi - The Mckoi Database
The Mckoi Database; the JDBC driver is in this package.
| com.mckoi.database |
com.mckoi.database - The core database classes for Mckoi
The core database classes for Mckoi.
Data Representation
A database is represented by a single
TableDataConglomerate,
which contains a collection of
MasterTableDataSource objects,
each of which represents a single table, including both committed and
uncommitted rows.
Access to a table is usually through the
TableDataSource interface, or its subclass
MutableTableDataSource
The
MasterTableDataSource objects
wrap themselves in an instance of the private class
MasterTableDataSource.MMutableTableDataSource, which implements
MutableTableDataSource.
The format of a table is defined by
DataTableDef, which is returned by
TableDataSource.getDataTableDef,
and which does not change during the lifetime of the table;
if the table format is changed, a new MasterTableDataSource is created
within the Transaction with the new format,
and the data and unchanged columns from the old table
are copied to the new one.
The format of a column is defined by
DataTableColumnDef.
Modifications to a row of a table are handled by a
RowData, which carries a reference to the
TableDataSource which it modified,
and from which data is retrieved.
Each column within the row is represented by a
DataCell,
which is either retrieved from the table or created by
DataCellFactory.
Transactions
A database can be associated with one or more simultaneous
Transaction objects.
All changes to the data in the database are done through Transactions.
The current set of open Transaction objects is managed by an
OpenTransactionList object,
which is pointed to by both the
TableDataConglomerate
and all of the
MasterTableDataSource
objects.
Changes to a row are handled by creating a new row in the
MasterTableDataSource
containing the changed
data plus any old data which is unchanged.
The data for the modified row are kept in a
RowData, which references a
QueryContext, which references a
DatabaseConnection, which references a
Transaction, which is the Transaction
under which that change was made.
Each field of the row is represented by a
DataCell.
When an application
issues an SQL request
to update the database, it eventually makes it down to
Statement.evaluate,
for example in Insert.
That evaluate method uses its
DatabaseConnection to get a
DataTable for a table name,
which is a wrapper around the
MutableTableDataSource
returned by the DatabaseConnection's
Transaction for the table of that name.
The MutableTableDataSource (created by
Transaction.getTable) is in turn a wrapper around a
MasterTableDataSource
created using the private class
MasterTableDataSource.MMutableTableDataSource.
The Statement uses its
DataTable to create a
RowData, then passes it to its
DataTable, which passes it to the
MutableTableDataSource,
which passes it to the
MasterTableDataSource,
which actually makes the change.
The Transaction maintains a
TransactionJournal, in which
are listed all of the tables which have been changed by the Transaction.
Eventually the
Transaction is closed
(committed or
rolled back),
which is handled by the
TableDataConglomerate
(
processCommit or
processRollback),
which, for each MasterTableDataSource, gets a
MasterTableJournal for it from the
TransactionJournal
specifying what changes have been made in that table
from this Transaction, and tells that
MasterTableDataSource
to commit or roll back the changes in that MasterTableJournal.
Locking
Locking is used to control concurrent access by two requests in the same
Transaction.
This is handled during
query execution
in
JDBCDatabaseInterface.execQuery
Each DatabaseConnection
has associated with it a single
LockingMechanism object,
which is used to
lock and
unlock
the DatabaseConnection's
Transaction as a whole.
The active lock is represented by a
LockHandle, which is returned by
LockingMechanism.lockTables,
and which is passed back to
LockingMechanism.unlockTables to drop the lock.
A lock on an individual table is represented by a Lock,
which is kept in a LockingQueue,
which maintains the link to the locked table.
Update Sequence
When a change is made to the database (insert, update, or delete),
the following list shows the sequence in which various steps are taken:
| com.mckoi.database.control | | com.mckoi.database.global |
com.mckoi.database.global - Constants
This package includes database constants such as
Types.
| com.mckoi.database.interpret |
com.mckoi.database.interpret - Interpret specific SQL statements
These classes interpret specific SQL statements, such as
Insert and
Delete.
| com.mckoi.database.jdbc |
com.mckoi.database.jdbc - JDBC interface to Mckoi
The JDBC interface to Mckoi.
Establishing a Connection
An application establishes a JDBC Connection by calling
java.sql.DriverManager.getConnection(String url, Properties info).
DriverManager.getConnection calls java.sql.Driver.connect, which
figures out that the URL is a Mckoi URL,
so calls
com.mckoi.database.jdbc.MDriver,
which was registered by a static initializer in
com.mckoi.JDBCDriver.
If the URL is local (embedded mode), MDriver creates an instance of
com.mckoi.database.jdbcserver.LocalDatabaseInterface,
which in turns creates and wraps up an instance of
com.mckoi.database.jdbcserver.JDBCDatabaseInterface,
and calls its
connectToJVM method to initialize it.
If the URL is remote (client/server mode), MDriver creates an instance of
TCPStreamDatabaseInterface
and calls its
connectToDatabase
method in order to establish a TCP connection to the
Mckoi database server.
For more information on how the server handles connections, see the package
com.mckoi.database.jdbcserver.
In either case, the resulting
DatabaseInterface
is wrapped up in a
MConnection,
and returned to the application as an instance of java.sql.Connection.
Executing a Query
When an application calls java.sql.Connection.createStatement() on its
MConnection, it gets back an instance of
MStatement,
which carries a pointer to the MConnection.
When the application calls java.sql.Statement.executeQuery(String) on
its MStatement, Mckoi creates an SQLQuery
from the String, creates an empty
MResultSet, then calls
MStatement.executeQuery
with those two objects.
MStatement.executeQuery turns around and calls
Mconnection.executeQuery,
which calls
execQuery on its
DatabaseInterface.
Depending on whether the connection is local or remote,
this call is either to
com.mckoi.database.jdbcserver.LocalDatabaseInterface.execQuery
for local connections, or to
RemoteDatabaseInterface.execQuery
for remote connections.
These are described more fully in the package description for
com.mckoi.database.jdbcserver
under
Local Queries
and
Remote Queries.
| com.mckoi.database.jdbcserver |
com.mckoi.database.jdbcserver - Server and embedded-database classes
Implementation of the DatabaseInterface interface,
including classes to handle local (embedded) mode
and remote (client/server) mode.
See DatabaseInterface.
Local (Embedded) mode
When accessing a local database, the client uses an instance of
LocalDatabaseInterface
(as set up while
Establishing a Connection)
to directly access the underlying database.
See Local Queries.
Remote (Client/Server) mode
When accessing a remote database,
requests in the client are directed to an instance of
JDBCDatabaseInterface
(as set up while
Establishing a Connection)
to send the requests over a TCP connection to the database server.
The server uses an instance of
LocalDatabaseInterface
to execute SQL statements in local mode on behalf of the client.
See Remote Queries.
Local Queries
When an application is accessing a local database,
or when considering query processing within the database server,
SQL queries all go through
LocalDatabaseInterface.execQuery.
This method uses
com.mckoi.database.DatabaseSystem.execute
to execute the
execQuery method
(see Query Execution)
of the contained
JDBCDatabaseInterface
in the first available
WorkerThread.
The calling thread waits for the WorkerThread to finish and return a
QueryResponse,
which is used by the caller to set up a
MResultSet.
Remote Queries
When an application is running in remote mode,
SQL queries are processed by the private ConnectionThread class within
com.mckoi.jdbc.RemoteDatabaseInterface.
The executeQuery method in this class writes the sql query string to
the socket attached to the server and returns an integer ID for that
sql request.
This is followed by a call to the getCommand method, which blocks until
it times out or until it gets a reply from the server for the right ID.
If a reply is received, the first byte is decoded as a status byte.
On success, an inner-class instance of
QueryResponse
is returned; on error, error info is read from the response and used
to create and throw an exception.
Data is written to the server in the calling thread.
There is a separate thread
(an instance of the private class RemoteDatabaseInterface.ConnectionThread in
RemoteDatabaseInterface)
to read the data coming back from the server,
which is placed into a buffer where it can be accessed by other threads.
Query Execution
Queries in local mode and queries handled by the database server
are both processed by
JDBCDatabaseInterface.execQuery.
This method always runs in a
WorkerThread.
The execQuery method takes these steps to execute the query:
- Set user and connection data into the WorkerThread.
- Output debug log info.
- Record start time.
- Parse sql statement into statement_tree, check cache.
- Bind values for query parameters.
- Prepare all expression in statement tree.
- Convert to instance of some
Statement subclass
(such as
Insert or
Delete.)
These are all in the package
com.mckoi.database.interpret.
- Set up locking.
- Finish preparing statement.
- Get list of tables to read and write.
- Lock tables.
- Evaluate the Statement using
Statement.evaluate.
This is different for each different type of Statement.
- Place results into result set cache.
- Unlock tables.
- Check autoCommit, do commit or rollback if set.
- Record end time.
- Return
QueryResponse
info (an instance of the private class JDIQueryResponse in
JDBCDatabaseInterface).
Service Initialization
After the database server has been started
and initialized its database, it begins listening for client connections.
This happens in
TCPServer.start.
The server creates a
ConnectionPoolServer,
either a
SingleThreadedConnectionPoolServer (when running in single-thead mode) or a
MultiThreadedConnectionPoolServer (when running in multi-thread mode).
The start method starts a listener thread and then returns.
The server listener thread sits in a loop blocked waiting for new connections.
When a new connection is accepted, the server creates a new
JDBCDatabaseInterface
for that connection, wraps it in a
TCPJDBCServerConnection,
and adds that to the
ConnectionPoolServer.
Client Requests
In single-thread mode,
the SingleThreadedConnectionPoolServer handles all client reads
in a single thread.
For each connection with a request, it calls
TCPJDBCServerConnection.processRequest on that connection,
using
com.mckoi.database.DatabaseSystem.execute
to execute it in a WorkerThread.
In multi-thread mode,
the MultiThreadedConnectionPoolServer starts a separate thread to handle
reads for each connection.
Each thread blocks until it has a request available, then calls
TCPJDBCServerConnection.processRequest on that connection,
using
com.mckoi.database.DatabaseSystem.execute
to execute it in a WorkerThread.
In either single-thread or multi-thread mode, client requests end up getting
passed to
TCPJDBCServerConnection.processRequest.
This method reads the command data, then calls
JDBCProcessor.processJDBCCommand with those bytes.
That method calls
JDBCProcessor.processQuery, which looks at the first byte of the
requests to see what it is.
If the request type is a database query (as opposed to retrieval of
part of a ResultSet), it creates a
SQLQuery from the data and calls
execQuery on its
JDBCDatabaseInterface
(see Query Execution above).
The result is encoded as a
QueryResponse,
which is converted back to bytes and written back to the client.
Note that this is all running in a
WorkerThread,
so the call to DatabaseInterface.execQuery is in a WorkerThread, as required.
If there is an exception during processing of a client request,
the message and traceback for the exception are encoded and
returned to the client, which recognizes the packet as an exception,
decodes the data on its side, and throws an exception in the client.
| com.mckoi.database.procedure | | com.mckoi.database.regexbridge |
com.mckoi.database.regexbridge - Implementations of the RegEx interface
Implementations of the RegexLibrary interface,
which allows the application to select which regular expression package
to use.
See RegexLibrary.
| com.mckoi.database.sql |
com.mckoi.database.sql - SQL parsing classes for Mckoi
These classes parse SQL statements in Mckoi.
The SQL syntax is defined in the file SQL.jj and compiled by
JavaCC into the SQL class.
| com.mckoi.debug |
com.mckoi.debug - Debugging classes
Debugging classes for Mckoi.
| com.mckoi.jfccontrols |
com.mckoi.jfccontrols - JFC extensions for use with Mckoi
JFC classes to access a Mckoi database from a Swing application.
| com.mckoi.runtime |
com.mckoi.runtime - Startup classes for Mckoi
The main (starting) class for a Mckoi database server.
Starting the Server
The database server is
started
by running
java -jar mckoidb.jar
The META-INF/MANIFEST file in the jar file specifies the starting class as
McKoiDBMain in this package, so java starts up
the server application at the
main
method of McKoiDBMain.
The main method prints a banner, parses options, loads the config file,
and eventually calls
BootMain.boot to complete the startup.
BootMain creates an instance of
Database, initializes it,
and finally
starts the service that listens for and handles client connections.
| com.mckoi.store | | com.mckoi.tools |
com.mckoi.tools - Tools for manipulating a Mckoi database
Tools for manipulating a Mckoi database.
| com.mckoi.util |
com.mckoi.util - Miscellaneous utility classes
Miscellaneous utility classes.
| gnu.regexp | | gnu.regexp.util | | net.sf.tapestry.contrib.mckoi | |
|