~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/******************************************************
2
Rollback segment
3
4
(c) 1996 Innobase Oy
5
6
Created 3/26/1996 Heikki Tuuri
7
*******************************************************/
8
9
#include "trx0rseg.h"
10
11
#ifdef UNIV_NONINL
12
#include "trx0rseg.ic"
13
#endif
14
15
#include "trx0undo.h"
16
#include "fut0lst.h"
17
#include "srv0srv.h"
18
#include "trx0purge.h"
19
20
/**********************************************************************
21
Looks for a rollback segment, based on the rollback segment id. */
22
23
trx_rseg_t*
24
trx_rseg_get_on_id(
25
/*===============*/
26
			/* out: rollback segment */
27
	ulint	id)	/* in: rollback segment id */
28
{
29
	trx_rseg_t*	rseg;
30
31
	rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
32
	ut_ad(rseg);
33
34
	while (rseg->id != id) {
35
		rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
36
		ut_ad(rseg);
37
	}
38
39
	return(rseg);
40
}
41
42
/********************************************************************
43
Creates a rollback segment header. This function is called only when
44
a new rollback segment is created in the database. */
45
46
ulint
47
trx_rseg_header_create(
48
/*===================*/
49
				/* out: page number of the created segment,
50
				FIL_NULL if fail */
51
	ulint	space,		/* in: space id */
52
	ulint	max_size,	/* in: max size in pages */
53
	ulint*	slot_no,	/* out: rseg id == slot number in trx sys */
54
	mtr_t*	mtr)		/* in: mtr */
55
{
56
	ulint		page_no;
57
	trx_rsegf_t*	rsegf;
58
	trx_sysf_t*	sys_header;
59
	ulint		i;
60
	page_t*		page;
61
62
	ut_ad(mtr);
63
	ut_ad(mutex_own(&kernel_mutex));
64
	ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space),
65
				MTR_MEMO_X_LOCK));
66
	sys_header = trx_sysf_get(mtr);
67
68
	*slot_no = trx_sysf_rseg_find_free(mtr);
69
70
	if (*slot_no == ULINT_UNDEFINED) {
71
72
		return(FIL_NULL);
73
	}
74
75
	/* Allocate a new file segment for the rollback segment */
76
	page = fseg_create(space, 0, TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr);
77
78
	if (page == NULL) {
79
		/* No space left */
80
81
		return(FIL_NULL);
82
	}
83
84
#ifdef UNIV_SYNC_DEBUG
85
	buf_page_dbg_add_level(page, SYNC_RSEG_HEADER_NEW);
86
#endif /* UNIV_SYNC_DEBUG */
87
88
	page_no = buf_frame_get_page_no(page);
89
90
	/* Get the rollback segment file page */
91
	rsegf = trx_rsegf_get_new(space, page_no, mtr);
92
93
	/* Initialize max size field */
94
	mlog_write_ulint(rsegf + TRX_RSEG_MAX_SIZE, max_size,
95
			 MLOG_4BYTES, mtr);
96
97
	/* Initialize the history list */
98
99
	mlog_write_ulint(rsegf + TRX_RSEG_HISTORY_SIZE, 0, MLOG_4BYTES, mtr);
100
	flst_init(rsegf + TRX_RSEG_HISTORY, mtr);
101
102
	/* Reset the undo log slots */
103
	for (i = 0; i < TRX_RSEG_N_SLOTS; i++) {
104
105
		trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr);
106
	}
107
108
	/* Add the rollback segment info to the free slot in the trx system
109
	header */
110
111
	trx_sysf_rseg_set_space(sys_header, *slot_no, space, mtr);
112
	trx_sysf_rseg_set_page_no(sys_header, *slot_no, page_no, mtr);
113
114
	return(page_no);
115
}
116
117
/***************************************************************************
118
Creates and initializes a rollback segment object. The values for the
119
fields are read from the header. The object is inserted to the rseg
120
list of the trx system object and a pointer is inserted in the rseg
121
array in the trx system object. */
122
static
123
trx_rseg_t*
124
trx_rseg_mem_create(
125
/*================*/
126
				/* out, own: rollback segment object */
127
	ulint	id,		/* in: rollback segment id */
128
	ulint	space,		/* in: space where the segment placed */
129
	ulint	page_no,	/* in: page number of the segment header */
130
	mtr_t*	mtr)		/* in: mtr */
131
{
132
	trx_rsegf_t*	rseg_header;
133
	trx_rseg_t*	rseg;
134
	trx_ulogf_t*	undo_log_hdr;
135
	fil_addr_t	node_addr;
136
	ulint		sum_of_undo_sizes;
137
	ulint		len;
138
139
	ut_ad(mutex_own(&kernel_mutex));
140
141
	rseg = mem_alloc(sizeof(trx_rseg_t));
142
143
	rseg->id = id;
144
	rseg->space = space;
145
	rseg->page_no = page_no;
146
147
	mutex_create(&rseg->mutex, SYNC_RSEG);
148
149
	UT_LIST_ADD_LAST(rseg_list, trx_sys->rseg_list, rseg);
150
151
	trx_sys_set_nth_rseg(trx_sys, id, rseg);
152
153
	rseg_header = trx_rsegf_get_new(space, page_no, mtr);
154
155
	rseg->max_size = mtr_read_ulint(rseg_header + TRX_RSEG_MAX_SIZE,
156
					MLOG_4BYTES, mtr);
157
158
	/* Initialize the undo log lists according to the rseg header */
159
160
	sum_of_undo_sizes = trx_undo_lists_init(rseg);
161
162
	rseg->curr_size = mtr_read_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
163
					 MLOG_4BYTES, mtr)
164
		+ 1 + sum_of_undo_sizes;
165
166
	len = flst_get_len(rseg_header + TRX_RSEG_HISTORY, mtr);
167
	if (len > 0) {
168
		trx_sys->rseg_history_len += len;
169
170
		node_addr = trx_purge_get_log_from_hist(
171
			flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr));
172
		rseg->last_page_no = node_addr.page;
173
		rseg->last_offset = node_addr.boffset;
174
175
		undo_log_hdr = trx_undo_page_get(rseg->space, node_addr.page,
176
						 mtr) + node_addr.boffset;
177
178
		rseg->last_trx_no = mtr_read_dulint(
179
			undo_log_hdr + TRX_UNDO_TRX_NO, mtr);
180
		rseg->last_del_marks = mtr_read_ulint(
181
			undo_log_hdr + TRX_UNDO_DEL_MARKS, MLOG_2BYTES, mtr);
182
	} else {
183
		rseg->last_page_no = FIL_NULL;
184
	}
185
186
	return(rseg);
187
}
188
189
/*************************************************************************
190
Creates the memory copies for rollback segments and initializes the
191
rseg list and array in trx_sys at a database startup. */
192
193
void
194
trx_rseg_list_and_array_init(
195
/*=========================*/
196
	trx_sysf_t*	sys_header,	/* in: trx system header */
197
	mtr_t*		mtr)		/* in: mtr */
198
{
199
	ulint	i;
200
	ulint	page_no;
201
	ulint	space;
202
203
	UT_LIST_INIT(trx_sys->rseg_list);
204
205
	trx_sys->rseg_history_len = 0;
206
207
	for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
208
209
		page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr);
210
211
		if (page_no == FIL_NULL) {
212
213
			trx_sys_set_nth_rseg(trx_sys, i, NULL);
214
		} else {
215
			space = trx_sysf_rseg_get_space(sys_header, i, mtr);
216
217
			trx_rseg_mem_create(i, space, page_no, mtr);
218
		}
219
	}
220
}
221
222
/********************************************************************
223
Creates a new rollback segment to the database. */
224
225
trx_rseg_t*
226
trx_rseg_create(
227
/*============*/
228
				/* out: the created segment object, NULL if
229
				fail */
230
	ulint	space,		/* in: space id */
231
	ulint	max_size,	/* in: max size in pages */
232
	ulint*	id,		/* out: rseg id */
233
	mtr_t*	mtr)		/* in: mtr */
234
{
235
	ulint		page_no;
236
	trx_rseg_t*	rseg;
237
238
	mtr_x_lock(fil_space_get_latch(space), mtr);
239
	mutex_enter(&kernel_mutex);
240
241
	page_no = trx_rseg_header_create(space, max_size, id, mtr);
242
243
	if (page_no == FIL_NULL) {
244
245
		mutex_exit(&kernel_mutex);
246
		return(NULL);
247
	}
248
249
	rseg = trx_rseg_mem_create(*id, space, page_no, mtr);
250
251
	mutex_exit(&kernel_mutex);
252
253
	return(rseg);
254
}