[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