You are here: Client-Server > Client-Container Pooling

Client-Container Pooling

When a client connects to the server, there's overhead to establish the connection. First the regular TCP-connection needs to be established. Then the server and client exchange meta data and finally the connection is ready. If you don't need a single or a few long during connections but rather short units of work on the client it is quite inefficient to open a client connection for each unit of work. In such scenarios you should consider to pool the client-containers.

Now simply pooling the raw client container might lead to issues. Each object-container has a reference-cache. When you pool the object-container and reuse it for some other work, this cache isn't cleared. This means that you might get dirty objects from the reference cache. You want to avoid this and have a clean cache when reusing the client container.

There's a way to archive that. On the client container the open session method creates a fresh object container with a clean reference cache which is sharing the transaction with the client. With this building block you can build a proper container pool. Download (C#, VB) the source code of a very simple example container pool.

First you need to create client connections on demand which will be pooled.

IObjectContainer client = Db4oClientServer.OpenClient("localhost", 
    Port, UserAndPassword, UserAndPassword);
ConnectionPoolExamples.cs: Open clients for the pool
Dim client As IObjectContainer = Db4oClientServer.OpenClient("localhost", _
             Port, UserAndPassword, UserAndPassword)
ConnectionPoolExamples.vb: Open clients for the pool

On a request for a object container, get a client container from the pool. Rollback the transaction on it to ensure that it is in a clean state.Then open a session container on it and use this session. The session-container ensures that the reference-cache is empty. Make sure that each client container is always used only once at any time, which means that there's always only one session-container open per client-container. The session-containers share the transaction with the client and you don't want to share transactions across multiple object containers.

// Obtain a client container. Either take one from the pool or allocate a new one
IObjectContainer client = ObtainClientContainer();
// Make sure that the transaction is in clean state
client.Rollback();
// Then create a session on that client container and use it for the database operations.
// The client-container is now in use. Ensure that it isn't leased twice.
IObjectContainer sessionContainer = client.Ext().OpenSession();
ConnectionPool.cs: Obtain a pooled container
' Obtain a client container. Either take one from the pool or allocate a new one
Dim client As IObjectContainer = ObtainClientContainer()
' Make sure that the transaction is in clean state
client.Rollback()
' Then create a session on that client container and use it for the database operations.
' The client-container is now in use. Ensure that it isn't leased twice.
Dim sessionContainer As IObjectContainer = client.Ext().OpenSession()
ConnectionPool.vb: Obtain a pooled container

Now when you're done with your operations, you can return the client to your pool of object containers. First close the session-container, which commits the changes and releases the resources. Then get the underlying client-container for that session and return it to the pool.

// First you need to get the underlying client for the session
IObjectContainer client = ClientForSession(session);
// then the client is ready for reuse
ReturnToThePool(client);
ConnectionPool.cs: Returning to pool
' First you need to get the underlying client for the session
Dim client As IObjectContainer = ClientForSession(session)
' then the client is ready for reuse
ReturnToThePool(client)
ConnectionPool.vb: Returning to pool