See: Description
Class | Description |
---|---|
AbstractJDBCDatabaseInterface |
An abstract implementation of JDBCDatabaseInterface that provides a
connection between a single DatabaseConnection and a DatabaseInterface
implementation.
|
DefaultLocalBootable |
A bootable object that filters through to a JDBCDatabaseInterface but
is thread-safe and multi-threaded.
|
JDBCDatabaseInterface |
An implementation of jdbc.DatabaseInterface on the server-side.
|
TCPServer |
A TCP/IP socket server that opens a single port and allows JDBC clients
to connect through the port to talk with the database.
|
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:
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.
Copyright © 2015. All rights reserved.