Building client applications

Every application using the ADB server has to connect it self to a so called object space. All objects created/modified are stored in this object space. Object spaces have to be created manually by means of the oosctl command.

Example 3-3. creating an object space

$ ooscntl --add snafu.local.net myobjects
ooscntl --add snafu.local.net myobjects
OSS Control Program, Version 0.1.0
Copyright (C) 2005; Michael Erdmann (http://gnade.sourceforge.net/)
 
Done.
$
      

The first argument is the name of the object space and the second is the directory where all objects of the name space will be placed in.

The name snafu.local.net is the object space identifier which could be every string but for transparency reasons the name should somehow indicate the purpose of the object space.

A typical application fragment is show below:

Example 3-4. Connecting to the database

procedure SDBClient is
    S   : Session.Object;
    .....
begin
   Trace.Start_Trace( Trace_File => "client" );		** (1)
   Trace.Trace_Level( 20 );
 
   Begin_Session( S, "snafu.local.net" ) ;		** (2)
 
   ...............

   End_Session( S );					** (3)
 
   Trace.Flush;						** (4)
 
exception
   when The_Error : others =>
      LOG( Trace.Flow, "*** Exception :" & Exception_Name( The_Error ) &
                          ", at " & Exception_Message( The_Error ) );
end SDBClient;
      

The statements at (1) are used to set the trace level and the trace file. The statement (2) connects the application to the object space. Such a connected task is called a session. (3) closes the session and (4) flushes the trace buffers before termination of the application.

The actual application code is placed between statement (2) and (3) which is always referring to the current thread but on the session object S any more.

Retrieving, modifying, deletion of objects are always done within a transaction. Every task can have only one transaction active. How to start a transaction is shown below:

Example 3-5. Starting a Transaction

declare
   T : Transaction_ID;
begin
   T := Start_Or_Join_Transaction;	       ** (5)
 
   .............................................
 
   Commit_Transaction;			       ** (6)
exception
    when The_Error : others =>
       Abort_Transaction;
       raise;
end;
      

A transaction is finished either by Commit_Transaction of Abort_Transaction. In case of Commit_Transaction all reserved objects are written back to the server. In case of an Abort_Transaction all modified objects are discarded.

Handling of exceptions

Since the code between (5) and (6) could always through exceptions every transaction should be put into a Ada 95 block with an exception handling in order to abort the transaction in case of unexpected exceptions. Otherwise the reserved objects could stay locked for an intended time, since the server does not know any thing about the client transactions.

Objects are identified either by a so called root name or the object identifier. There are two ways of fetching objects:

Reserve_Object fetches the contents of an object from the server and locks this object with respect to other reservations. The object is addressed either by means of a root name or an object identifier.

Fetch_Object simply retrieves a copy of the object but the object is not locked at all. There for it is not part of any transaction.

In order to make object creation a little bit simpler, the the SDB.Session package provides a method which is called Get_Object. This method creates the object if it is not already existing or fetched the object. In both cases the object will be reserved.

A typical fragment is shown below. Part of the object is a field called Seq. If this field is 0 (3) then the object is freshly created. If so we set the objects field by means of the procedure Set (3) and afterwards the Seq field is incremented (4). Is the object is not newly created we simply increment the Seq field (4). At the end the changes are commited towards the server.

Example 3-6. Changing the object

       T := Start_Or_Join_Transaction;	                      ** (1)
 							       
       Get_Object( P, Name => "Michael" );		      ** (2)
 
       if Seq( P ) = 0 then				      ** (3)
          Set( P, "Michael", "Erdmann", 20 );
       end if;
       ....
 
       Increment( P );                                        ** (4)
 
       Commit_Transaction;				      ** (5)