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 |
}
|