Simple Access Berkeley DB Using STLdb4

STLdb4 makes C++ programming with the Berkeley DB simpler and more effective.

Transactions are supported either by passing an explicit transaction object to each method or by setting the implicit transaction on Database objects. The latter style can be very convenient in cases when the overloaded array operator is used, which does not allow a transaction object to be passed in (only one argument can be passed to the array operator).

When explicitly passing a transaction object to the database for each method call, the Transaction class has the commit() and abort() methods either to ensure the data is stored safely on disk or the whole transaction is fully reverted. When the last reference to a transaction object goes out of scope, it will call commit() in its destructor if it was not already committed or aborted.

If you are operating on only one database, you can largely avoid the Transaction class and use the start() method of the Database class to begin an implicit transaction. When using an implicit transaction, the commit() and abort() methods of the Database class perform the transaction finalization actions.

The simplest method of using transactions is shown in Listing 8. Things of note in the example include the use of a database environment, which in this case will include initialization of the Berkeley DB transaction subsystem. A transaction object must be passed to the Database object when it is created. In the Database constructor, I pass a new Transaction that will be handed in as an fh_trans smart pointer, which will clean up the Transaction object for me after the Database object is constructed. When executed, the Initial value and Final value lines will print the same information to cerr.

The same transaction can be used with multiple databases by holding onto the transaction object smart pointer and associating it with each database. This is shown in Listing 9. The second part of the example uses setImplicitTransaction() to associate the databases with the current transaction.

The default action of a Transaction object can be changed to calling abort() by setting setDefaultDestructionIsAbort(true) on the transaction object. This is very handy for use with a Resource Acquisition Is Initialization (RAII) programming style to revert a transaction automatically if any exception occurs in a code block. This RAII style is shown in Listing 10. The code block marked starting at the comment (AA) sets the default destruction action for a transaction to call abort() and then modifies the database with this transaction. An exception is explicitly thrown that will cause the Transaction object to be destroyed (its last reference being the one held by tr on the stack). This will call abort() for the transaction, and we will eventually print the old “bar” value at the end of the example.

The Database::iterator class uses Berkeley DB cursors in its implementation, so the transaction we pass to Database::find() will be used for any operations performed on the database iterator. For example, if getIOStream() was called on diter, STLdb4 would be performing partial I/O using the transaction tr on the Berkeley DB file behind the API.

This use of RAII is very handy for code that wants to make changes to the database in one go, but that might throw an exception along the way.

The setImplicitTransaction() call should be avoided when performing RAII, because it will have the Database keep a smart pointer to the Transaction that will prolong the call to abort() if an exception is thrown.



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

STLdb4 looks good but seems a pain to compile

Rich20B's picture

Having read the article STLdb4 looks very good, though trying to get it compiled and installed is a pain.

If anybody else is having problems then I've written my experiences of compiling on Debian Etch here:


Anonymous's picture

After reading this article, I have been using STLdb4, and am very pleased with it! It could use a few touchups, but since you can
always get the raw BerkeleyDB pointer there's nothing I haven't been
able to accomplish yet. *SO* much nicer to work with than the existing C++ implementation. Good job!