+static pthread_key_t tsdkey;
+
+#define MYCURSOR (((struct cdbtsd*)pthread_getspecific(tsdkey))->cursor)
+#define MYTID (((struct cdbtsd*)pthread_getspecific(tsdkey))->tid)
+
+/* just a little helper function */
+static int txabort(DB_TXN *tid) {
+ int ret = txn_abort(tid);
+
+ if (ret)
+ lprintf(1, "txn_abort: %s\n", db_strerror(ret));
+
+ return ret;
+}
+
+/* this one is even more helpful than the last. */
+static int txcommit(DB_TXN *tid) {
+ int ret = txn_commit(tid, 0);
+
+ if (ret)
+ lprintf(1, "txn_commit: %s\n", db_strerror(ret));
+
+ return ret;
+}
+
+/* are you sensing a pattern yet? */
+static int txbegin(DB_TXN **tid) {
+ int ret = txn_begin(dbenv, NULL, tid, 0);
+
+ if (ret)
+ lprintf(1, "txn_begin: %s\n", db_strerror(ret));
+
+ return ret;
+}
+
+static void release_handles(void *arg) {
+ if (arg != NULL) {
+ struct cdbtsd *tsd = (struct cdbtsd *)arg;
+
+ if (tsd->cursor != NULL) {
+ lprintf(1, "WARNING: cursor still in progress; "
+ "closing!\n");
+ tsd->cursor->c_close(tsd->cursor);
+ }
+
+ if (tsd->tid != NULL) {
+ lprintf(1, "ERROR: transaction still in progress; "
+ "aborting!\n");
+ txabort(tsd->tid);
+ }
+ }
+}
+
+static void dest_tsd(void *arg) {
+ if (arg != NULL) {
+ release_handles(arg);
+ phree(arg);
+ }
+}