~drizzle-trunk/drizzle/development

1455.3.1 by Vladimir Kolesnikov
lp:drizzle + pbxt 1.1 + test results
1
/* Copyright (c) 2005 PrimeBase Technologies GmbH
2
 *
3
 * PrimeBase XT
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
 *
19
 * 2005-04-10	Paul McCullagh
20
 *
21
 * H&G2JCtL
22
 */
23
#ifndef __xt_xaction_h__
24
#define __xt_xaction_h__
25
26
#include "filesys_xt.h"
27
#include "lock_xt.h"
28
29
struct XTThread;
30
struct XTDatabase;
31
struct XTOpenTable;
32
33
#ifdef DEBUG
34
//#define XT_USE_XACTION_DEBUG_SIZES
35
#endif
36
37
#ifdef XT_USE_XACTION_DEBUG_SIZES
38
39
#define XT_TN_NUMBER_INCREMENT	20
40
#define XT_TN_MAX_TO_FREE		20
41
#define XT_TN_MAX_TO_FREE_WASTE	3
42
#define XT_TN_MAX_TO_FREE_CHECK	3
43
#define XT_TN_MAX_TO_FREE_INC	3
44
45
#define XT_XN_SEGMENT_SHIFTS	1
46
47
#else
48
49
#define XT_TN_NUMBER_INCREMENT	100		// The increment of the transaction number on restart
50
#define XT_TN_MAX_TO_FREE		800		// The maximum size of the "to free" list
51
#define XT_TN_MAX_TO_FREE_WASTE	400
52
#define XT_TN_MAX_TO_FREE_CHECK	100		// Once we have exceeded the limit, we only try in intervals
53
#define XT_TN_MAX_TO_FREE_INC	100
54
55
//#define XT_XN_SEGMENT_SHIFTS	5		// (32)
56
//#define XT_XN_SEGMENT_SHIFTS	6		// (64)
57
//#define XT_XN_SEGMENT_SHIFTS	7		// (128)
58
#define XT_XN_SEGMENT_SHIFTS	8		// (256)
59
//#define XT_XN_SEGMENT_SHIFTS	9		// (512)
60
61
#endif
62
63
/* The hash table size (a prime number) */
64
#if XT_XN_SEGMENT_SHIFTS == 1		// (1)
65
#define XT_XN_HASH_TABLE_SIZE	1301
66
#elif XT_XN_SEGMENT_SHIFTS == 5		// (32)
67
#define XT_XN_HASH_TABLE_SIZE	1009
68
#elif XT_XN_SEGMENT_SHIFTS == 6		// (64)
69
#define XT_XN_HASH_TABLE_SIZE	503
70
#elif XT_XN_SEGMENT_SHIFTS == 7		// (128)
71
#define XT_XN_HASH_TABLE_SIZE	251
72
#elif XT_XN_SEGMENT_SHIFTS == 8		// (256)
73
#define XT_XN_HASH_TABLE_SIZE	127
74
#elif XT_XN_SEGMENT_SHIFTS == 9		// (512)
75
#define XT_XN_HASH_TABLE_SIZE	67
76
#endif
77
78
/* Number of pre-allocated transaction data structures per segment */
79
#define XT_XN_DATA_ALLOC_COUNT	XT_XN_HASH_TABLE_SIZE
80
81
#define XT_XN_NO_OF_SEGMENTS	(1 << XT_XN_SEGMENT_SHIFTS)
82
#define XT_XN_SEGMENT_MASK		(XT_XN_NO_OF_SEGMENTS - 1)
83
84
#define XT_XN_XAC_LOGGED		1
85
#define XT_XN_XAC_ENDED			2					/* The transaction has ended. */
86
#define XT_XN_XAC_COMMITTED		4					/* The transaction was committed. */
87
#define XT_XN_XAC_CLEANED		8					/* The transaction has been cleaned. */
88
#define XT_XN_XAC_RECOVERED		16					/* This transaction was detected on recovery. */
89
#define XT_XN_XAC_SWEEP			32					/* End ID has been set, OK to sweep. */
90
#define XT_XN_XAC_PREPARED		64					/* The transaction was prepared (used only by recovery). */
91
92
#define XT_XN_VISIBLE			0					/* The transaction is committed, and the record is visible. */
93
#define XT_XN_NOT_VISIBLE		1					/* The transaction is committed, but not visible. */
94
#define XT_XN_ABORTED			2					/* Transaction was aborted. */
95
#define XT_XN_MY_UPDATE			3					/* The record was update by me. */
96
#define XT_XN_OTHER_UPDATE		4					/* The record was updated by someone else. */
97
#define XT_XN_REREAD			5					/* The transaction is not longer in RAM, status is unkown, retry. */
98
99
typedef struct XTXactPrepare {
100
	xtXactID					xp_xact_id;
101
	xtWord4						xp_hash;
102
	struct XTXactPrepare		*xp_next;			/* Next item in hash table. */
103
	int							xp_data_len;
104
	xtWord1						xp_xa_data[XT_MAX_XA_DATA_SIZE];
105
} XTXactPrepareRec, *XTXactPreparePtr;
106
107
typedef struct XTXactXA {
108
	xtXactID					xx_xact_id;
109
	XTXactPreparePtr			xx_xa_ptr;
110
} XTXactXARec, *XTXactXAPtr;
111
112
typedef struct XTXactEnumXA {
113
	u_int						exa_index;
114
	xtBool						exa_locked;
115
} XTXactEnumXARec, *XTXactEnumXAPtr;
116
117
typedef struct XTXactData {
118
	xtXactID					xd_start_xn_id;			/* Note: may be zero!. */
119
	xtXactID					xd_end_xn_id;			/* Note: may be zero!. */
120
121
	/* The begin position: */
122
	xtLogID						xd_begin_log;			/* Non-zero if begin has been logged. */
123
	xtLogOffset					xd_begin_offset;
124
	int							xd_flags;
125
	xtWord4						xd_end_time;
126
	xtThreadID					xd_thread_id;
127
	xtWord4						xd_xa_hash;				/* 0 if no XA transaction. */
128
129
	/* A transaction may be indexed twice in the hash table.
130
	 * Once on the start sequence number, and once on the
131
	 * end sequence number.
132
	 */
133
	struct XTXactData			*xd_next_xact;		/* Next pointer in the hash table, also used by the free list. */
134
135
} XTXactDataRec, *XTXactDataPtr;
136
137
#ifdef XT_NO_ATOMICS
138
#define XT_XACT_USE_PTHREAD_RW
139
#else
140
#define XT_XACT_USE_SPINXSLOCK
141
#endif
142
143
#if defined(XT_XACT_USE_PTHREAD_RW)
144
#define XT_XACT_LOCK_TYPE				xt_rwlock_type
145
#define XT_XACT_INIT_LOCK(s, i)			xt_init_rwlock_with_autoname(s, i)
146
#define XT_XACT_FREE_LOCK(s, i)			xt_free_rwlock(i)	
147
#define XT_XACT_READ_LOCK(i, s)			xt_slock_rwlock_ns(i)
148
#define XT_XACT_WRITE_LOCK(i, s)		xt_xlock_rwlock_ns(i)
149
#define XT_XACT_UNLOCK(i, s, b)			xt_unlock_rwlock_ns(i)
150
#elif defined(XT_XACT_USE_SPINXSLOCK)
151
#define XT_XACT_LOCK_TYPE				XTSpinXSLockRec
152
#define XT_XACT_INIT_LOCK(s, i)			xt_spinxslock_init_with_autoname(s, i)
153
#define XT_XACT_FREE_LOCK(s, i)			xt_spinxslock_free(s, i)	
154
#define XT_XACT_READ_LOCK(i, s)			xt_spinxslock_slock(i)
155
#define XT_XACT_WRITE_LOCK(i, s)		xt_spinxslock_xlock(i, FALSE, (s)->t_id)
156
#define XT_XACT_UNLOCK(i, s, b)			xt_spinxslock_unlock(i, b)
157
#else
158
#error Please define the lock type
159
#endif
160
161
/* We store the transactions in a number of segments, each
162
 * segment has a hash table.
163
 */
164
typedef struct XTXactSeg {
165
	XT_XACT_LOCK_TYPE			xs_tab_lock;						/* Lock for hash table. */
166
	xtXactID					xs_last_xn_id;						/* The last transaction ID added. */
167
	XTXactDataPtr				xs_free_list;						/* List of transaction data structures. */
168
	XTXactDataPtr				xs_table[XT_XN_HASH_TABLE_SIZE];	/* Hash table containing the transaction data structures. */
169
} XTXactSegRec, *XTXactSegPtr;
170
171
typedef struct XTXactWait {
172
	xtXactID					xw_xn_id;
173
} XTXactWaitRec, *XTXactWaitPtr;
174
175
void			xt_xn_init_db(struct XTThread *self, struct XTDatabase *db);
176
void			xt_xn_exit_db(struct XTThread *self, struct XTDatabase *db);
177
void			xt_start_sweeper(struct XTThread *self, struct XTDatabase *db);
178
void			xt_init_sweeper_wait(struct XTThread *self, struct XTDatabase *db);
179
void			xt_wait_for_sweeper(struct XTThread *self, struct XTDatabase *db, int abort_time);
180
void			xt_stop_sweeper(struct XTThread *self, struct XTDatabase *db);
181
182
void			xt_xn_init_thread(struct XTThread *self, int what_for);
183
void			xt_xn_exit_thread(struct XTThread *self);
184
void			xt_wakeup_sweeper(struct XTDatabase *db);
185
186
xtBool			xt_xn_begin(struct XTThread *self);
187
xtBool			xt_xn_commit(struct XTThread *self);
188
xtBool			xt_xn_rollback(struct XTThread *self);
189
xtBool			xt_xn_log_tab_id(struct XTThread *self, xtTableID tab_id);
190
int				xt_xn_status(struct XTOpenTable *ot, xtXactID xn_id, xtRecordID rec_id);
191
xtBool			xt_xn_wait_for_xact(struct XTThread *self, XTXactWaitPtr xw, struct XTLockWait *lw);
192
xtXactID		xt_xn_get_curr_id(struct XTDatabase *db);
193
xtWord8			xt_xn_bytes_to_sweep(struct XTDatabase *db, struct XTThread *thread);
194
195
int				xt_xn_xa_compare(struct XTThread *self, register const void *thunk, register const void *a, register const void *b);
196
xtBool			xt_xn_prepare(int len, xtWord1 *xa_data, struct XTThread *thread);
197
xtBool			xt_xn_store_xa_data(struct XTDatabase *db, xtXactID xn_id, int len, xtWord1 *xa_data, struct XTThread *thread);
198
void			xt_xn_delete_xa_data_by_xact(struct XTDatabase *db, xtXactID xact_id, struct XTThread *thread);
199
void			xt_xn_delete_xa_data(struct XTDatabase *db, XTXactPreparePtr xap, xtBool unlock, struct XTThread *thread);
200
XTXactPreparePtr	xt_xn_find_xa_data(struct XTDatabase *db, int len, xtWord1 *xa_data, xtBool lock, struct XTThread *thread);
201
XTXactPreparePtr	xt_xn_enum_xa_data(struct XTDatabase *db, XTXactEnumXAPtr exa);
202
203
XTXactDataPtr	xt_xn_add_old_xact(struct XTDatabase *db, xtXactID xn_id, struct XTThread *thread);
204
XTXactDataPtr	xt_xn_get_xact(struct XTDatabase *db, xtXactID xn_id, struct XTThread *thread);
205
xtBool			xt_xn_delete_xact(struct XTDatabase *db, xtXactID xn_id, struct XTThread *thread);
206
207
inline xtXactID	xt_xn_diff(register xtXactID now, register xtXactID then)
208
{
209
	if ((now - then) > (xtXactID) 0xFFFFFFFF/2)
210
		return then - now;
211
	return now - then;
212
}
213
214
inline xtBool	xt_xn_is_before(register xtXactID now, register xtXactID then)
215
{
216
	if (now >= then) {
217
		if ((now - then) > (xtXactID) 0xFFFFFFFF/2)
218
			return TRUE;
219
		return FALSE;
220
	}
221
	if ((then - now) > (xtXactID) 0xFFFFFFFF/2)
222
		return FALSE;
223
	return TRUE;
224
}
225
226
#endif