1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1997-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12 13#include "db_cxx.h" 14#include "dbinc/cxx_int.h" 15 16#include "dbinc/txn.h" 17 18// Helper macro for simple methods that pass through to the 19// underlying C method. It may return an error or raise an exception. 20// Note this macro expects that input _argspec is an argument 21// list element (e.g., "char *arg") and that _arglist is the arguments 22// that should be passed through to the C method (e.g., "(db, arg)") 23// 24#define DBTXN_METHOD(_name, _delete, _argspec, _arglist) \ 25int DbTxn::_name _argspec \ 26{ \ 27 int ret; \ 28 DB_TXN *txn = unwrap(this); \ 29 DbEnv *dbenv = DbEnv::get_DbEnv(txn->mgrp->env->dbenv); \ 30 \ 31 ret = txn->_name _arglist; \ 32 /* Weird, but safe if we don't access this again. */ \ 33 if (_delete) { \ 34 /* Can't do this in the destructor. */ \ 35 if (parent_txn_ != NULL) \ 36 parent_txn_->remove_child_txn(this); \ 37 delete this; \ 38 } \ 39 if (!DB_RETOK_STD(ret)) \ 40 DB_ERROR(dbenv, "DbTxn::" # _name, ret, ON_ERROR_UNKNOWN); \ 41 return (ret); \ 42} 43 44// private constructor, never called but needed by some C++ linkers 45DbTxn::DbTxn(DbTxn *ptxn) 46: imp_(0) 47{ 48 TAILQ_INIT(&children); 49 memset(&child_entry, 0, sizeof(child_entry)); 50 parent_txn_ = ptxn; 51 if (parent_txn_ != NULL) 52 parent_txn_->add_child_txn(this); 53} 54 55DbTxn::DbTxn(DB_TXN *txn, DbTxn *ptxn) 56: imp_(txn) 57{ 58 txn->api_internal = this; 59 TAILQ_INIT(&children); 60 memset(&child_entry, 0, sizeof(child_entry)); 61 parent_txn_ = ptxn; 62 if (parent_txn_ != NULL) 63 parent_txn_->add_child_txn(this); 64} 65 66DbTxn::~DbTxn() 67{ 68 DbTxn *txn, *pnext; 69 70 for(txn = TAILQ_FIRST(&children); txn != NULL;) { 71 pnext = TAILQ_NEXT(txn, child_entry); 72 delete txn; 73 txn = pnext; 74 } 75} 76 77DBTXN_METHOD(abort, 1, (), (txn)) 78DBTXN_METHOD(commit, 1, (u_int32_t flags), (txn, flags)) 79DBTXN_METHOD(discard, 1, (u_int32_t flags), (txn, flags)) 80 81void DbTxn::remove_child_txn(DbTxn *kid) 82{ 83 TAILQ_REMOVE(&children, kid, child_entry); 84 kid->set_parent(NULL); 85} 86 87void DbTxn::add_child_txn(DbTxn *kid) 88{ 89 TAILQ_INSERT_HEAD(&children, kid, child_entry); 90 kid->set_parent(this); 91} 92 93u_int32_t DbTxn::id() 94{ 95 DB_TXN *txn; 96 97 txn = unwrap(this); 98 return (txn->id(txn)); // no error 99} 100 101DBTXN_METHOD(get_name, 0, (const char **namep), (txn, namep)) 102DBTXN_METHOD(prepare, 0, (u_int8_t *gid), (txn, gid)) 103DBTXN_METHOD(set_name, 0, (const char *name), (txn, name)) 104DBTXN_METHOD(set_timeout, 0, (db_timeout_t timeout, u_int32_t flags), 105 (txn, timeout, flags)) 106 107// static method 108DbTxn *DbTxn::wrap_DB_TXN(DB_TXN *txn) 109{ 110 DbTxn *wrapped_txn = get_DbTxn(txn); 111 // txn may have a valid parent transaction, but here we don't care. 112 // We maintain parent-kid relationship in DbTxn only to make sure 113 // unresolved kids of DbTxn objects are deleted. 114 return (wrapped_txn != NULL) ? wrapped_txn : new DbTxn(txn, NULL); 115} 116