xa_db.c 5.23 KB
Newer Older
unknown's avatar
unknown committed
1 2 3
/*-
 * See the file LICENSE for redistribution information.
 *
unknown's avatar
unknown committed
4
 * Copyright (c) 1998-2005
unknown's avatar
unknown committed
5
 *	Sleepycat Software.  All rights reserved.
unknown's avatar
unknown committed
6
 *
unknown's avatar
unknown committed
7
 * $Id: xa_db.c,v 12.4 2005/10/20 18:57:16 bostic Exp $
unknown's avatar
unknown committed
8 9 10 11 12 13 14 15 16
 */

#include "db_config.h"

#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#endif

#include "db_int.h"
unknown's avatar
unknown committed
17
#include "dbinc/txn.h"
unknown's avatar
unknown committed
18 19 20 21 22

static int __xa_close __P((DB *, u_int32_t));
static int __xa_cursor __P((DB *, DB_TXN *, DBC **, u_int32_t));
static int __xa_del __P((DB *, DB_TXN *, DBT *, u_int32_t));
static int __xa_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
unknown's avatar
unknown committed
23
static int __xa_open __P((DB *, DB_TXN *,
unknown's avatar
unknown committed
24 25
	    const char *, const char *, DBTYPE, u_int32_t, int));
static int __xa_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
unknown's avatar
unknown committed
26 27
static int __xa_set_txn __P((DB *, DB_TXN **, int));
static int __xa_truncate __P((DB *, DB_TXN *, u_int32_t *, u_int32_t));
unknown's avatar
unknown committed
28 29 30 31 32 33

typedef struct __xa_methods {
	int (*close) __P((DB *, u_int32_t));
	int (*cursor) __P((DB *, DB_TXN *, DBC **, u_int32_t));
	int (*del) __P((DB *, DB_TXN *, DBT *, u_int32_t));
	int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
unknown's avatar
unknown committed
34
	int (*open) __P((DB *, DB_TXN *,
unknown's avatar
unknown committed
35 36
	    const char *, const char *, DBTYPE, u_int32_t, int));
	int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t));
unknown's avatar
unknown committed
37
	int (*truncate) __P((DB *, DB_TXN *, u_int32_t *, u_int32_t));
unknown's avatar
unknown committed
38 39
} XA_METHODS;

unknown's avatar
unknown committed
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
/*
 * __xa_set_txn --
 *	Find a transaction handle.
 */
static int
__xa_set_txn(dbp, txnpp, no_xa_txn)
	DB *dbp;
	DB_TXN **txnpp;
	int no_xa_txn;
{
	DB_ENV *dbenv;
	int ret;

	dbenv = dbp->dbenv;

	/*
	 * It doesn't make sense for a server to specify a DB_TXN handle.
	 * As the server can't know if other operations it has done have
	 * committed/aborted, it can self-deadlock.  If the server wants
	 * other transactions, it can open other DB handles and use them.
	 * Disallow specified DB_TXN handles.
	 */
	if (*txnpp != NULL) {
		__db_err(dbenv,
    "transaction handles should not be directly specified to XA interfaces");
		return (EINVAL);
	}

	/* See if the TM has declared a transaction. */
	if ((ret = __xa_get_txn(dbenv, txnpp, 0)) != 0)
		return (ret);
	if ((*txnpp)->txnid != TXN_INVALID)
		return (0);

	/*
	 * We may be opening databases in the server initialization routine.
	 * In that case, it's reasonable not to have an XA transaction.  It's
	 * also reasonable to open a database as part of an XA transaction,
	 * allow both.
	 */
	if (no_xa_txn) {
		*txnpp = NULL;
		return (0);
	}

	__db_err(dbenv, "no XA transaction declared");
	return (EINVAL);
unknown's avatar
unknown committed
87 88
}

unknown's avatar
unknown committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102
/*
 * __db_xa_create --
 *	DB XA constructor.
 *
 * PUBLIC: int __db_xa_create __P((DB *));
 */
int
__db_xa_create(dbp)
	DB *dbp;
{
	XA_METHODS *xam;
	int ret;

	/*
unknown's avatar
unknown committed
103 104
	 * Allocate the XA internal structure, and wrap the open and close
	 * calls.
unknown's avatar
unknown committed
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
	 */
	if ((ret = __os_calloc(dbp->dbenv, 1, sizeof(XA_METHODS), &xam)) != 0)
		return (ret);

	dbp->xa_internal = xam;
	xam->open = dbp->open;
	dbp->open = __xa_open;
	xam->close = dbp->close;
	dbp->close = __xa_close;

	return (0);
}

/*
 * __xa_open --
 *	XA open wrapper.
 */
static int
unknown's avatar
unknown committed
123
__xa_open(dbp, txn, name, subdb, type, flags, mode)
unknown's avatar
unknown committed
124
	DB *dbp;
unknown's avatar
unknown committed
125
	DB_TXN *txn;
unknown's avatar
unknown committed
126 127 128 129 130 131 132 133 134 135
	const char *name, *subdb;
	DBTYPE type;
	u_int32_t flags;
	int mode;
{
	XA_METHODS *xam;
	int ret;

	xam = (XA_METHODS *)dbp->xa_internal;

unknown's avatar
unknown committed
136 137 138 139
	if ((ret =
	    __xa_set_txn(dbp, &txn, LF_ISSET(DB_AUTO_COMMIT) ? 1 : 0)) != 0)
		return (ret);
	if ((ret = xam->open(dbp, txn, name, subdb, type, flags, mode)) != 0)
unknown's avatar
unknown committed
140 141
		return (ret);

unknown's avatar
unknown committed
142
	/* Wrap any DB handle method that takes a TXN ID as an argument. */
unknown's avatar
unknown committed
143 144 145 146
	xam->cursor = dbp->cursor;
	xam->del = dbp->del;
	xam->get = dbp->get;
	xam->put = dbp->put;
unknown's avatar
unknown committed
147
	xam->truncate = dbp->truncate;
unknown's avatar
unknown committed
148 149 150 151
	dbp->cursor = __xa_cursor;
	dbp->del = __xa_del;
	dbp->get = __xa_get;
	dbp->put = __xa_put;
unknown's avatar
unknown committed
152
	dbp->truncate = __xa_truncate;
unknown's avatar
unknown committed
153 154 155 156 157 158 159 160 161 162 163

	return (0);
}

static int
__xa_cursor(dbp, txn, dbcp, flags)
	DB *dbp;
	DB_TXN *txn;
	DBC **dbcp;
	u_int32_t flags;
{
unknown's avatar
unknown committed
164
	int ret;
unknown's avatar
unknown committed
165

unknown's avatar
unknown committed
166 167 168 169
	if ((ret = __xa_set_txn(dbp, &txn, 0)) != 0)
		return (ret);
	return (((XA_METHODS *)
	    dbp->xa_internal)->cursor(dbp, txn, dbcp, flags));
unknown's avatar
unknown committed
170 171 172 173 174 175 176 177 178
}

static int
__xa_del(dbp, txn, key, flags)
	DB *dbp;
	DB_TXN *txn;
	DBT *key;
	u_int32_t flags;
{
unknown's avatar
unknown committed
179
	int ret;
unknown's avatar
unknown committed
180

unknown's avatar
unknown committed
181 182 183
	if ((ret = __xa_set_txn(dbp, &txn, 0)) != 0)
		return (ret);
	return (((XA_METHODS *)dbp->xa_internal)->del(dbp, txn, key, flags));
unknown's avatar
unknown committed
184 185 186 187 188 189 190 191 192 193 194
}

static int
__xa_close(dbp, flags)
	DB *dbp;
	u_int32_t flags;
{
	int (*real_close) __P((DB *, u_int32_t));

	real_close = ((XA_METHODS *)dbp->xa_internal)->close;

unknown's avatar
unknown committed
195
	__os_free(dbp->dbenv, dbp->xa_internal);
unknown's avatar
unknown committed
196 197 198 199 200 201 202 203 204 205 206 207
	dbp->xa_internal = NULL;

	return (real_close(dbp, flags));
}

static int
__xa_get(dbp, txn, key, data, flags)
	DB *dbp;
	DB_TXN *txn;
	DBT *key, *data;
	u_int32_t flags;
{
unknown's avatar
unknown committed
208
	int ret;
unknown's avatar
unknown committed
209

unknown's avatar
unknown committed
210 211 212 213
	if ((ret = __xa_set_txn(dbp, &txn, 0)) != 0)
		return (ret);
	return (((XA_METHODS *)
	    dbp->xa_internal)->get(dbp, txn, key, data, flags));
unknown's avatar
unknown committed
214 215 216 217 218 219 220 221 222
}

static int
__xa_put(dbp, txn, key, data, flags)
	DB *dbp;
	DB_TXN *txn;
	DBT *key, *data;
	u_int32_t flags;
{
unknown's avatar
unknown committed
223
	int ret;
unknown's avatar
unknown committed
224

unknown's avatar
unknown committed
225 226 227 228 229 230 231 232 233 234 235 236 237
	if ((ret = __xa_set_txn(dbp, &txn, 0)) != 0)
		return (ret);
	return (((XA_METHODS *)
	    dbp->xa_internal)->put(dbp, txn, key, data, flags));
}

static int
__xa_truncate(dbp, txn, countp, flags)
	DB *dbp;
	DB_TXN *txn;
	u_int32_t *countp, flags;
{
	int ret;
unknown's avatar
unknown committed
238

unknown's avatar
unknown committed
239 240 241 242
	if ((ret = __xa_set_txn(dbp, &txn, 0)) != 0)
		return (ret);
	return (((XA_METHODS *)
	    dbp->xa_internal)->truncate(dbp, txn, countp, flags));
unknown's avatar
unknown committed
243
}