Drizzled Public API Documentation

mtr0mtr.cc
1 /*****************************************************************************
2 
3 Copyright (C) 1995, 2009, Innobase Oy. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
8 
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15 St, Fifth Floor, Boston, MA 02110-1301 USA
16 
17 *****************************************************************************/
18 
19 /**************************************************/
26 #include "mtr0mtr.h"
27 
28 #ifdef UNIV_NONINL
29 #include "mtr0mtr.ic"
30 #endif
31 
32 #include "buf0buf.h"
33 #include "buf0flu.h"
34 #include "page0types.h"
35 #include "mtr0log.h"
36 #include "log0log.h"
37 
38 #ifndef UNIV_HOTBACKUP
39 # include "log0recv.h"
40 /*****************************************************************/
42 static
43 void
44 mtr_memo_slot_release(
45 /*==================*/
46  mtr_t* mtr,
47  mtr_memo_slot_t* slot)
48 {
49  void* object;
50  ulint type;
51 
52  ut_ad(mtr);
53  ut_ad(slot);
54 
55 #ifndef UNIV_DEBUG
56  UT_NOT_USED(mtr);
57 #endif /* UNIV_DEBUG */
58 
59  object = slot->object;
60  type = slot->type;
61 
62  if (UNIV_LIKELY(object != NULL)) {
63  if (type <= MTR_MEMO_BUF_FIX) {
64  buf_page_release((buf_block_t*)object, type);
65  } else if (type == MTR_MEMO_S_LOCK) {
66  rw_lock_s_unlock((rw_lock_t*)object);
67 #ifdef UNIV_DEBUG
68  } else if (type != MTR_MEMO_X_LOCK) {
69  ut_ad(type == MTR_MEMO_MODIFY);
70  ut_ad(mtr_memo_contains(mtr, object,
71  MTR_MEMO_PAGE_X_FIX));
72 #endif /* UNIV_DEBUG */
73  } else {
74  rw_lock_x_unlock((rw_lock_t*)object);
75  }
76  }
77 
78  slot->object = NULL;
79 }
80 
81 /**********************************************************/
85 static
86 void
87 mtr_memo_pop_all(
88 /*=============*/
89  mtr_t* mtr)
90 {
91  mtr_memo_slot_t* slot;
92  dyn_array_t* memo;
93  ulint offset;
94 
95  ut_ad(mtr);
96  ut_ad(mtr->magic_n == MTR_MAGIC_N);
97  ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in
98  commit */
99  memo = &(mtr->memo);
100 
101  offset = dyn_array_get_data_size(memo);
102 
103  while (offset > 0) {
104  offset -= sizeof(mtr_memo_slot_t);
105  slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
106 
107  mtr_memo_slot_release(mtr, slot);
108  }
109 }
110 
111 /*****************************************************************/
113 static
114 void
115 mtr_memo_slot_note_modification(
116 /*============================*/
117  mtr_t* mtr,
118  mtr_memo_slot_t* slot)
119 {
120  ut_ad(mtr);
121  ut_ad(mtr->magic_n == MTR_MAGIC_N);
122  ut_ad(mtr->modifications);
123 
124  if (slot->object != NULL && slot->type == MTR_MEMO_PAGE_X_FIX) {
125  buf_block_t* block = (buf_block_t*) slot->object;
126 
127 #ifdef UNIV_DEBUG
129 #endif /* UNIV_DEBUG */
130  buf_flush_note_modification(block, mtr);
131  }
132 }
133 
134 /**********************************************************/
141 static
142 void
143 mtr_memo_note_modifications(
144 /*========================*/
145  mtr_t* mtr)
146 {
147  dyn_array_t* memo;
148  ulint offset;
149 
150  ut_ad(mtr);
151  ut_ad(mtr->magic_n == MTR_MAGIC_N);
152  ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in
153  commit */
154  memo = &mtr->memo;
155 
156  offset = dyn_array_get_data_size(memo);
157 
158  while (offset > 0) {
159  mtr_memo_slot_t* slot;
160 
161  offset -= sizeof(mtr_memo_slot_t);
162  slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
163 
164  mtr_memo_slot_note_modification(mtr, slot);
165  }
166 }
167 
168 /************************************************************/
170 static
171 void
172 mtr_log_reserve_and_write(
173 /*======================*/
174  mtr_t* mtr)
175 {
176  dyn_array_t* mlog;
177  dyn_block_t* block;
178  ulint data_size;
179  byte* first_data;
180 
181  ut_ad(mtr);
182 
183  mlog = &(mtr->log);
184 
185  first_data = dyn_block_get_data(mlog);
186 
187  if (mtr->n_log_recs > 1) {
189  } else {
190  *first_data = (byte)((ulint)*first_data
192  }
193 
194  if (mlog->heap == NULL) {
195  mtr->end_lsn = log_reserve_and_write_fast(
196  first_data, dyn_block_get_used(mlog),
197  &mtr->start_lsn);
198  if (mtr->end_lsn) {
199 
200  /* Success. We have the log mutex.
201  Add pages to flush list and exit */
202  goto func_exit;
203  }
204  }
205 
206  data_size = dyn_array_get_data_size(mlog);
207 
208  /* Open the database log for log_write_low */
209  mtr->start_lsn = log_reserve_and_open(data_size);
210 
211  if (mtr->log_mode == MTR_LOG_ALL) {
212 
213  block = mlog;
214 
215  while (block != NULL) {
217  dyn_block_get_used(block));
218  block = dyn_array_get_next_block(mlog, block);
219  }
220  } else {
221  ut_ad(mtr->log_mode == MTR_LOG_NONE);
222  /* Do nothing */
223  }
224 
225  mtr->end_lsn = log_close();
226 
227 func_exit:
229 
230  /* It is now safe to release the log mutex because the
231  flush_order mutex will ensure that we are the first one
232  to insert into the flush list. */
233  log_release();
234 
235  if (mtr->modifications) {
236  mtr_memo_note_modifications(mtr);
237  }
238 
240 }
241 #endif /* !UNIV_HOTBACKUP */
242 
243 /***************************************************************/
245 UNIV_INTERN
246 void
248 /*=======*/
249  mtr_t* mtr)
250 {
251  ut_ad(mtr);
252  ut_ad(mtr->magic_n == MTR_MAGIC_N);
253  ut_ad(mtr->state == MTR_ACTIVE);
254  ut_ad(!mtr->inside_ibuf);
255  ut_d(mtr->state = MTR_COMMITTING);
256 
257 #ifndef UNIV_HOTBACKUP
258  /* This is a dirty read, for debugging. */
259  ut_ad(!recv_no_log_write);
260 
261  if (mtr->modifications && mtr->n_log_recs) {
262  mtr_log_reserve_and_write(mtr);
263  }
264 
265  mtr_memo_pop_all(mtr);
266 #endif /* !UNIV_HOTBACKUP */
267 
268  ut_d(mtr->state = MTR_COMMITTED);
269  dyn_array_free(&(mtr->memo));
270  dyn_array_free(&(mtr->log));
271 }
272 
273 #ifndef UNIV_HOTBACKUP
274 /**********************************************************/
278 UNIV_INTERN
279 void
281 /*======================*/
282  mtr_t* mtr,
283  ulint savepoint)
284 {
285  mtr_memo_slot_t* slot;
286  dyn_array_t* memo;
287  ulint offset;
288 
289  ut_ad(mtr);
290  ut_ad(mtr->magic_n == MTR_MAGIC_N);
291  ut_ad(mtr->state == MTR_ACTIVE);
292 
293  memo = &(mtr->memo);
294 
295  offset = dyn_array_get_data_size(memo);
296  ut_ad(offset >= savepoint);
297 
298  while (offset > savepoint) {
299  offset -= sizeof(mtr_memo_slot_t);
300 
301  slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
302 
303  ut_ad(slot->type != MTR_MEMO_MODIFY);
304 
305  /* We do not call mtr_memo_slot_note_modification()
306  because there MUST be no changes made to the buffer
307  pages after the savepoint */
308  mtr_memo_slot_release(mtr, slot);
309  }
310 }
311 
312 /***************************************************/
314 UNIV_INTERN
315 void
317 /*=============*/
318  mtr_t* mtr,
319  void* object,
320  ulint type)
321 {
322  mtr_memo_slot_t* slot;
323  dyn_array_t* memo;
324  ulint offset;
325 
326  ut_ad(mtr);
327  ut_ad(mtr->magic_n == MTR_MAGIC_N);
328  ut_ad(mtr->state == MTR_ACTIVE);
329 
330  memo = &(mtr->memo);
331 
332  offset = dyn_array_get_data_size(memo);
333 
335  while (offset > 0) {
336  offset -= sizeof(mtr_memo_slot_t);
337 
338  slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
339 
340  if (object == slot->object && type == slot->type) {
341 
342  /* We cannot release a page that has been written
343  to in the middle of a mini-transaction. */
344 
345  ut_ad(!(mtr->modifications
346  && slot->type == MTR_MEMO_PAGE_X_FIX));
347 
348  mtr_memo_slot_release(mtr, slot);
349 
350  break;
351  }
352  }
354 }
355 #endif /* !UNIV_HOTBACKUP */
356 
357 /********************************************************/
360 UNIV_INTERN
361 ulint
363 /*===========*/
364  const byte* ptr,
365  ulint type,
366  mtr_t* /*mtr __attribute__((unused))*/)
368 {
369  ut_ad(mtr->state == MTR_ACTIVE);
370  ut_ad(mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_S_FIX)
371  || mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_X_FIX));
372  if (type == MLOG_1BYTE) {
373  return(mach_read_from_1(ptr));
374  } else if (type == MLOG_2BYTES) {
375  return(mach_read_from_2(ptr));
376  } else {
377  ut_ad(type == MLOG_4BYTES);
378  return(mach_read_from_4(ptr));
379  }
380 }
381 
382 #ifdef UNIV_DEBUG
383 # ifndef UNIV_HOTBACKUP
384 /**********************************************************/
387 UNIV_INTERN
388 ibool
389 mtr_memo_contains_page(
390 /*===================*/
391  mtr_t* mtr,
392  const byte* ptr,
393  ulint type)
394 {
395  return(mtr_memo_contains(mtr, buf_block_align(ptr), type));
396 }
397 
398 /*********************************************************/
400 UNIV_INTERN
401 void
402 mtr_print(
403 /*======*/
404  mtr_t* mtr)
405 {
406  fprintf(stderr,
407  "Mini-transaction handle: memo size %lu bytes"
408  " log size %lu bytes\n",
409  (ulong) dyn_array_get_data_size(&(mtr->memo)),
410  (ulong) dyn_array_get_data_size(&(mtr->log)));
411 }
412 # endif /* !UNIV_HOTBACKUP */
413 #endif /* UNIV_DEBUG */