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