1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2000,2008 Oracle. All rights reserved. 5 * 6 * $Id: db_cds.c,v 12.14 2008/01/08 20:58:10 bostic Exp $ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#include "dbinc/db_page.h" 13#include "dbinc/db_am.h" 14#include "dbinc/lock.h" 15#include "dbinc/txn.h" 16 17static int __cdsgroup_abort __P((DB_TXN *txn)); 18static int __cdsgroup_commit __P((DB_TXN *txn, u_int32_t flags)); 19static int __cdsgroup_discard __P((DB_TXN *txn, u_int32_t flags)); 20static u_int32_t __cdsgroup_id __P((DB_TXN *txn)); 21static int __cdsgroup_notsup __P((ENV *env, const char *meth)); 22static int __cdsgroup_prepare __P((DB_TXN *txn, u_int8_t *gid)); 23static int __cdsgroup_set_name __P((DB_TXN *txn, const char *name)); 24static int __cdsgroup_set_timeout 25 __P((DB_TXN *txn, db_timeout_t timeout, u_int32_t flags)); 26 27/* 28 * __cdsgroup_notsup -- 29 * Error when CDS groups don't support a method. 30 */ 31static int 32__cdsgroup_notsup(env, meth) 33 ENV *env; 34 const char *meth; 35{ 36 __db_errx(env, "CDS groups do not support %s", meth); 37 return (DB_OPNOTSUP); 38} 39 40static int 41__cdsgroup_abort(txn) 42 DB_TXN *txn; 43{ 44 return (__cdsgroup_notsup(txn->mgrp->env, "abort")); 45} 46 47static int 48__cdsgroup_commit(txn, flags) 49 DB_TXN *txn; 50 u_int32_t flags; 51{ 52 DB_LOCKER *locker; 53 DB_LOCKREQ lreq; 54 ENV *env; 55 int ret, t_ret; 56 57 COMPQUIET(flags, 0); 58 env = txn->mgrp->env; 59 60 /* Check for live cursors. */ 61 if (txn->cursors != 0) { 62 __db_errx(env, "CDS group has active cursors"); 63 return (EINVAL); 64 } 65 66 /* We may be holding handle locks; release them. */ 67 lreq.op = DB_LOCK_PUT_ALL; 68 lreq.obj = NULL; 69 ret = __lock_vec(env, txn->locker, 0, &lreq, 1, NULL); 70 71 env = txn->mgrp->env; 72 locker = txn->locker; 73 __os_free(env, txn->mgrp); 74 __os_free(env, txn); 75 if ((t_ret = __lock_id_free(env, locker)) != 0 && ret == 0) 76 ret = t_ret; 77 return (ret); 78} 79 80static int __cdsgroup_discard(txn, flags) 81 DB_TXN *txn; 82 u_int32_t flags; 83{ 84 COMPQUIET(flags, 0); 85 return (__cdsgroup_notsup(txn->mgrp->env, "discard")); 86} 87 88static u_int32_t __cdsgroup_id(txn) 89 DB_TXN *txn; 90{ 91 return (txn->txnid); 92} 93 94static int __cdsgroup_prepare(txn, gid) 95 DB_TXN *txn; 96 u_int8_t *gid; 97{ 98 COMPQUIET(gid, NULL); 99 return (__cdsgroup_notsup(txn->mgrp->env, "prepare")); 100} 101 102static int __cdsgroup_set_name(txn, name) 103 DB_TXN *txn; 104 const char *name; 105{ 106 COMPQUIET(name, NULL); 107 return (__cdsgroup_notsup(txn->mgrp->env, "set_name")); 108} 109 110static int __cdsgroup_set_timeout(txn, timeout, flags) 111 DB_TXN *txn; 112 db_timeout_t timeout; 113 u_int32_t flags; 114{ 115 COMPQUIET(timeout, 0); 116 COMPQUIET(flags, 0); 117 return (__cdsgroup_notsup(txn->mgrp->env, "set_timeout")); 118} 119 120/* 121 * __cds_txn_begin -- 122 * ENV->cdsgroup_begin 123 * 124 * PUBLIC: int __cdsgroup_begin __P((DB_ENV *, DB_TXN **)); 125 */ 126int 127__cdsgroup_begin(dbenv, txnpp) 128 DB_ENV *dbenv; 129 DB_TXN **txnpp; 130{ 131 DB_THREAD_INFO *ip; 132 DB_TXN *txn; 133 ENV *env; 134 int ret; 135 136 env = dbenv->env; 137 138 ENV_ILLEGAL_BEFORE_OPEN(env, "cdsgroup_begin"); 139 if (!CDB_LOCKING(env)) 140 return (__env_not_config(env, "cdsgroup_begin", DB_INIT_CDB)); 141 142 ENV_ENTER(env, ip); 143 *txnpp = txn = NULL; 144 if ((ret = __os_calloc(env, 1, sizeof(DB_TXN), &txn)) != 0) 145 goto err; 146 /* 147 * We need a dummy DB_TXNMGR -- it's the only way to get from a 148 * transaction handle to the environment handle. 149 */ 150 if ((ret = __os_calloc(env, 1, sizeof(DB_TXNMGR), &txn->mgrp)) != 0) 151 goto err; 152 txn->mgrp->env = env; 153 154 if ((ret = __lock_id(env, &txn->txnid, &txn->locker)) != 0) 155 goto err; 156 157 txn->flags = TXN_CDSGROUP; 158 txn->abort = __cdsgroup_abort; 159 txn->commit = __cdsgroup_commit; 160 txn->discard = __cdsgroup_discard; 161 txn->id = __cdsgroup_id; 162 txn->prepare = __cdsgroup_prepare; 163 txn->set_name = __cdsgroup_set_name; 164 txn->set_timeout = __cdsgroup_set_timeout; 165 166 *txnpp = txn; 167 168 if (0) { 169err: if (txn != NULL) { 170 if (txn->mgrp != NULL) 171 __os_free(env, txn->mgrp); 172 __os_free(env, txn); 173 } 174 } 175 ENV_LEAVE(env, ip); 176 return (ret); 177} 178