Berkeley DB Reference Guide:
Programmer Notes


Error returns to applications

Except for the historic dbm, ndbm, and hsearch interfaces, Berkeley DB does not use the global variable errno to return error values. The return values for all Berkeley DB functions are grouped into the following three categories:

A return value of 0 indicates that the operation was successful.

> 0
A return value that is greater than 0 indicates that there was a system error. The errno value returned by the system is returned by the function; for example, when a Berkeley DB function is unable to allocate memory, the return value from the function will be ENOMEM.

< 0
A return value that is less than 0 indicates a condition that was not a system failure, but was not an unqualified success, either. For example, a routine to retrieve a key/data pair from the database may return DB_NOTFOUND when the key/data pair does not appear in the database; as opposed to the value of 0, which would be returned if the key/data pair were found in the database.

All values returned by Berkeley DB functions are less than 0 in order to avoid conflict with possible values of errno. Specifically, Berkeley DB reserves all values from -30,800 to -30,999 to itself as possible error values. There are a few Berkeley DB interfaces where it is possible for an application function to be called by a Berkeley DB function and subsequently fail with an application-specific return. Such failure returns will be passed back to the function that originally called a Berkeley DB interface. To avoid ambiguity about the cause of the error, error values separate from the Berkeley DB error name space should be used.

Although possible error returns are specified by each individual function's manual page, there are a few error returns that deserve general mention:


There are two special return values that are similar in meaning and that are returned in similar situations, and therefore might be confused: DB_NOTFOUND and DB_KEYEMPTY.

The DB_NOTFOUND error return indicates that the requested key/data pair did not exist in the database or that start-of- or end-of-file has been reached by a cursor.

The DB_KEYEMPTY error return indicates that the requested key/data pair logically exists but was never explicitly created by the application (the Recno and Queue access methods will automatically create key/data pairs under some circumstances; see DB->open for more information), or that the requested key/data pair was deleted and never re-created. In addition, the Queue access method will return DB_KEYEMPTY for records that were created as part of a transaction that was later aborted and never re-created.


The DB_KEYEXIST error return indicates the DB_NOOVERWRITE option was specified to the DB->put function and the key already exists in the database.


When a database cannot be flushed to disk by DB->close or DB->sync, or by the underlying Memory Pool subsystem methods, memp_fsync and memp_sync, DB_INCOMPLETE may be returned to the application.

In the case of DB->close and DB->sync, the only reason for a return of DB_INCOMPLETE is if another thread of control was writing pages in the underlying database file at the same time as the DB->close or DB->sync call was made. For this reason, a return of DB_INCOMPLETE can normally be ignored; or, in cases where it is a possible return value, DB->sync should probably never have been called, or the DB_NOSYNC option should have been specified to DB->close.

In the case of memp_fsync or memp_sync (or other Berkeley DB interfaces that call those functions, txn_checkpoint for example), a return of DB_INCOMPLETE indicates that the database environment is under heavy load and the checkpoint was unable to complete because there were pages that could not be written at this time. This is not a fatal error, and the call should be retried.


When multiple threads of control are modifying the database, there is normally the potential for deadlock. In Berkeley DB, deadlock is signified by an error return from the Berkeley DB function of the value DB_LOCK_DEADLOCK. Whenever a Berkeley DB function returns DB_LOCK_DEADLOCK, the enclosing transaction should be aborted.

Any Berkeley DB function that attempts to acquire locks can potentially return DB_LOCK_DEADLOCK. Practically speaking, the safest way to deal with applications that can deadlock is to handle a DB_LOCK_DEADLOCK return from any Berkeley DB access method call.


When multiple threads of control are modifying the database, there is normally the potential for deadlock. In order to avoid deadlock, applications may specify -- on a per-transaction basis -- that if a lock is unavailable, the Berkeley DB operation should return immediately instead of waiting on the lock. The error return in this case will be DB_LOCK_NOTGRANTED. Whenever a Berkeley DB function returns DB_LOCK_NOTGRANTED, the enclosing transaction should be aborted.


There exists a class of errors that Berkeley DB considers fatal to an entire Berkeley DB environment. An example of this type of error is a corrupted database or a log write failure because the disk is out of free space. The only way to recover from these failures is to have all threads of control exit the Berkeley DB environment, run recovery of the environment, and re-enter Berkeley DB. (It is not strictly necessary that the processes exit, although that is the only way to recover system resources, such as file descriptors and memory, allocated by Berkeley DB.)

When this type of error is encountered, the error value DB_RUNRECOVERY is returned. This error can be returned by any Berkeley DB interface. Once DB_RUNRECOVERY is returned by any interface, it will be returned from all subsequent Berkeley DB calls made by any threads of control participating in the environment.

Optionally, applications may also specify a fatal-error callback function using the DB_ENV->set_paniccall function. This callback function will be called with two arguments: a reference to the DB_ENV structure associated with the environment and the errno value associated with the underlying error that caused the problem.

Applications can handle such fatal errors in one of two ways: by checking for DB_RUNRECOVERY as part of their normal Berkeley DB error return checking, similarly to DB_LOCK_DEADLOCK or any other error, or by simply exiting the application when the callback function is called in applications that have no cleanup processing of their own.


Copyright Sleepycat Software