summaryrefslogtreecommitdiff
path: root/cxx/cxx_txn.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cxx/cxx_txn.cpp')
-rw-r--r--cxx/cxx_txn.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/cxx/cxx_txn.cpp b/cxx/cxx_txn.cpp
new file mode 100644
index 0000000..28b9344
--- /dev/null
+++ b/cxx/cxx_txn.cpp
@@ -0,0 +1,115 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1997-2009 Oracle. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+#include "db_cxx.h"
+#include "dbinc/cxx_int.h"
+
+#include "dbinc/txn.h"
+
+// Helper macro for simple methods that pass through to the
+// underlying C method. It may return an error or raise an exception.
+// Note this macro expects that input _argspec is an argument
+// list element (e.g., "char *arg") and that _arglist is the arguments
+// that should be passed through to the C method (e.g., "(db, arg)")
+//
+#define DBTXN_METHOD(_name, _delete, _argspec, _arglist) \
+int DbTxn::_name _argspec \
+{ \
+ int ret; \
+ DB_TXN *txn = unwrap(this); \
+ DbEnv *dbenv = DbEnv::get_DbEnv(txn->mgrp->env->dbenv); \
+ \
+ ret = txn->_name _arglist; \
+ /* Weird, but safe if we don't access this again. */ \
+ if (_delete) { \
+ /* Can't do this in the destructor. */ \
+ if (parent_txn_ != NULL) \
+ parent_txn_->remove_child_txn(this); \
+ delete this; \
+ } \
+ if (!DB_RETOK_STD(ret)) \
+ DB_ERROR(dbenv, "DbTxn::" # _name, ret, ON_ERROR_UNKNOWN); \
+ return (ret); \
+}
+
+// private constructor, never called but needed by some C++ linkers
+DbTxn::DbTxn(DbTxn *ptxn)
+: imp_(0)
+{
+ TAILQ_INIT(&children);
+ memset(&child_entry, 0, sizeof(child_entry));
+ parent_txn_ = ptxn;
+ if (parent_txn_ != NULL)
+ parent_txn_->add_child_txn(this);
+}
+
+DbTxn::DbTxn(DB_TXN *txn, DbTxn *ptxn)
+: imp_(txn)
+{
+ txn->api_internal = this;
+ TAILQ_INIT(&children);
+ memset(&child_entry, 0, sizeof(child_entry));
+ parent_txn_ = ptxn;
+ if (parent_txn_ != NULL)
+ parent_txn_->add_child_txn(this);
+}
+
+DbTxn::~DbTxn()
+{
+ DbTxn *txn, *pnext;
+
+ for(txn = TAILQ_FIRST(&children); txn != NULL;) {
+ pnext = TAILQ_NEXT(txn, child_entry);
+ delete txn;
+ txn = pnext;
+ }
+}
+
+DBTXN_METHOD(abort, 1, (), (txn))
+DBTXN_METHOD(commit, 1, (u_int32_t flags), (txn, flags))
+DBTXN_METHOD(discard, 1, (u_int32_t flags), (txn, flags))
+
+void DbTxn::remove_child_txn(DbTxn *kid)
+{
+ TAILQ_REMOVE(&children, kid, child_entry);
+ kid->set_parent(NULL);
+}
+
+void DbTxn::add_child_txn(DbTxn *kid)
+{
+ TAILQ_INSERT_HEAD(&children, kid, child_entry);
+ kid->set_parent(this);
+}
+
+u_int32_t DbTxn::id()
+{
+ DB_TXN *txn;
+
+ txn = unwrap(this);
+ return (txn->id(txn)); // no error
+}
+
+DBTXN_METHOD(get_name, 0, (const char **namep), (txn, namep))
+DBTXN_METHOD(prepare, 0, (u_int8_t *gid), (txn, gid))
+DBTXN_METHOD(set_name, 0, (const char *name), (txn, name))
+DBTXN_METHOD(set_timeout, 0, (db_timeout_t timeout, u_int32_t flags),
+ (txn, timeout, flags))
+
+// static method
+DbTxn *DbTxn::wrap_DB_TXN(DB_TXN *txn)
+{
+ DbTxn *wrapped_txn = get_DbTxn(txn);
+ // txn may have a valid parent transaction, but here we don't care.
+ // We maintain parent-kid relationship in DbTxn only to make sure
+ // unresolved kids of DbTxn objects are deleted.
+ return (wrapped_txn != NULL) ? wrapped_txn : new DbTxn(txn, NULL);
+}