[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Ozone doc project: sample
Sorry, this is a repost; had forgotten subject...
====
Hi everyone,
although I am still waiting for comments on the TOC I posted before really
getting into things, I wanted to present an example of what the developer
doc could be like (I mean, from a content point of view, forget
presentation for now). Of course, eventually, diagrams will be added. But
for now it is just plain text.
I was thinking, maybe we should try to include design pattern terminology
in our docs, especially developer docs. As architectures grow more complex,
this could be of great help to developers that are digging to understand
the sources. To me, stating that this or that group of classes/interfaces
implement a given pattern does already a lot as far as documentation goes;
whole ensembles of software components become almost self-describing with a
few pattern mentions here an there.
For that purpose, you will see I introduced design pattern references in
the doc, just to show. Is the way I do it THE way? I don't know; I am
waiting for your opinion on that. And I do not want to fall in the trap of
desperately trying to find a pattern just for the sake of it. I mean, let's
be pragmatic.
So here it goes:
Ozone Documentation Project
Ozone Developer Documentation
Client-side
================================
Connecting to Ozone
--------------------------------
org.ozoneDB.ExternalDatabase
1- Factory behavior
This abtract class implements the OzoneInterface interface and, as such,
the behavior common to most instances of OzoneInterface. This class acts as
a proxy [pattern: Proxy, source: ...] hiding the type of access to Ozone
(remote or local) behind a single abstraction. Client applications need
only "opening" an underlying physical database using the proper URL syntax,
which this class interprets to return the proper child class instance of
ExternalDatabase, namely: org.ozoneDB.LocalDatabase or
org.ozoneDB.RemoteDatabase.
Concretely, client applications obtain an ExternalDatabase intance through
one of the static openDatabase(...) methods. The factory methods [pattern:
Abstract Factory Method, source: ...] expect the URL string passed to them
to begin with one of the following patterns: "ozonedb:local" or
"ozonedb:remote", corresponding respectively to LocalDatabase and
RemoteDatabase.
Subclasses of ExternalDatabase are expected to implement the following
abstract method [pattern: Template Method, source: ...]:
protected abstract DbClient newConnection() throws Exception;
2- org.ozoneDB.LocalDatabase vs org.ozoneDB.RemoteDatabase
An instance of LocalDatabase is used when application and Ozone server are
in the same Virtual Machine, meaning that there is no network layer
separating application and server. The LocalDatabase's newConnection()
method is implemented in the following way
protected DbClient newConnection() throws Exception {
return new DbLocalClient( this, theEnv, userName );
}
An instance of RemoteDatabase is used, as opposed to a LocalDatabase, when
the client application is communicating with a remote Ozone server. As
such, a RemoteDatabase instance relays commands to a remote server.
protected DbClient newConnection() throws Exception {
if (portNum == 0) {
throw new DbNotOpenExc();
}
DbClient connection = new DbRemoteClient( this, hostname, portNum, userName );
sendCommand( new DbOpen( userName ), true, connection );
return connection;
}
3- Thread management and connection pooling
One instance of ExternalDatabase can be used safely in a multi-threaded
context, although the ExternalDatabase class does not maintain one
connection per thread, which is considered too resource-intensive. Instead,
ExternalDatabase maintains a pool of connections (i.e.:
org.ozoneDB.core.DbRemote.DbClient instances) [pattern: Pool, source: ...]
that are recycled among many client threads, except in the context of a
transaction: in such a case, the thread is registered with a connection
until the transaction is over, after which the connection is pooled.
The following excerpt illustrates that logic:
// code from sendCommand( DbCommand command, boolean waitForResult )
Thread thread = Thread.currentThread();
AbstractTransaction txOfThread =
(AbstractTransaction)txTable.elementForKey( thread );
if (txOfThread != null) {
DbClient connection = txOfThread.connection;
return sendCommand( command, waitForResult, connection );
}
else {
DbClient connection = null;
try {
connection = acquirePooledConnection();
return sendCommand( command, waitForResult, connection );
}
finally {
releasePooledConnection( connection );
}
}
This code shows that if a thread is associated to a transaction, the
connection encapsulated within that transaction object is used.
---------------
Yanick