1#include <db_cxx.h>
2
3/*
4 * Resource-acquisition-as-initialization pattern for Berkeley DB's cursors.
5 *
6 * Use DbcAuto instead of Berkeley DB's builtin Dbc class.  The constructor
7 * allocates a new cursor, and it is freed automatically when it goes out of
8 * scope.
9 *
10 * Note that some care is required with the order in which Berkeley DB handles
11 * are closed.  In particular, the cursor handle must be closed before any
12 * database or transaction handles the cursor references.  In addition, the
13 * cursor close method can throw exceptions, which are masked by the destructor.
14 *
15 * For these reasons, you are strongly advised to call the DbcAuto::close
16 * method in the non-exceptional case.  This class exists to ensure that
17 * cursors are closed if an exception occurs.
18 */
19class DbcAuto {
20public:
21	DbcAuto(Db *db, DbTxn *txn, u_int32_t flags) {
22		db->cursor(txn, &dbc_, flags);
23	}
24
25	~DbcAuto() {
26		try {
27			close();
28		} catch(...) {
29			// Ignore it, another exception is pending
30		}
31	}
32
33	void close() {
34		if (dbc_) {
35			// Set the member to 0 before making the call in
36			// case an exception is thrown.
37			Dbc *tdbc = dbc_;
38			dbc_ = 0;
39			tdbc->close();
40		}
41	}
42
43	operator Dbc *() {
44		return dbc_;
45	}
46
47	operator Dbc **() {
48		return &dbc_;
49	}
50
51	Dbc *operator->() {
52		return dbc_;
53	}
54
55private:
56	Dbc *dbc_;
57};
58