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_d(mtr->state = MTR_COMMITTING);
255 
256 #ifndef UNIV_HOTBACKUP
257  /* This is a dirty read, for debugging. */
258  ut_ad(!recv_no_log_write);
259 
260  if (mtr->modifications && mtr->n_log_recs) {
261  mtr_log_reserve_and_write(mtr);
262  }
263 
264  mtr_memo_pop_all(mtr);
265 #endif /* !UNIV_HOTBACKUP */
266 
267  ut_d(mtr->state = MTR_COMMITTED);
268  dyn_array_free(&(mtr->memo));
269  dyn_array_free(&(mtr->log));
270 }
271 
272 #ifndef UNIV_HOTBACKUP
273 /**********************************************************/
277 UNIV_INTERN
278 void
280 /*======================*/
281  mtr_t* mtr,
282  ulint savepoint)
283 {
284  mtr_memo_slot_t* slot;
285  dyn_array_t* memo;
286  ulint offset;
287 
288  ut_ad(mtr);
289  ut_ad(mtr->magic_n == MTR_MAGIC_N);
290  ut_ad(mtr->state == MTR_ACTIVE);
291 
292  memo = &(mtr->memo);
293 
294  offset = dyn_array_get_data_size(memo);
295  ut_ad(offset >= savepoint);
296 
297  while (offset > savepoint) {
298  offset -= sizeof(mtr_memo_slot_t);
299 
300  slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
301 
302  ut_ad(slot->type != MTR_MEMO_MODIFY);
303 
304  /* We do not call mtr_memo_slot_note_modification()
305  because there MUST be no changes made to the buffer
306  pages after the savepoint */
307  mtr_memo_slot_release(mtr, slot);
308  }
309 }
310 
311 /***************************************************/
313 UNIV_INTERN
314 void
316 /*=============*/
317  mtr_t* mtr,
318  void* object,
319  ulint type)
320 {
321  mtr_memo_slot_t* slot;
322  dyn_array_t* memo;
323  ulint offset;
324 
325  ut_ad(mtr);
326  ut_ad(mtr->magic_n == MTR_MAGIC_N);
327  ut_ad(mtr->state == MTR_ACTIVE);
328 
329  memo = &(mtr->memo);
330 
331  offset = dyn_array_get_data_size(memo);
332 
334  while (offset > 0) {
335  offset -= sizeof(mtr_memo_slot_t);
336 
337  slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
338 
339  if (object == slot->object && type == slot->type) {
340 
341  /* We cannot release a page that has been written
342  to in the middle of a mini-transaction. */
343 
344  ut_ad(!(mtr->modifications
345  && slot->type == MTR_MEMO_PAGE_X_FIX));
346 
347  mtr_memo_slot_release(mtr, slot);
348 
349  break;
350  }
351  }
353 }
354 #endif /* !UNIV_HOTBACKUP */
355 
356 /********************************************************/
359 UNIV_INTERN
360 ulint
362 /*===========*/
363  const byte* ptr,
364  ulint type,
365  mtr_t* /*mtr __attribute__((unused))*/)
367 {
368  ut_ad(mtr->state == MTR_ACTIVE);
369  ut_ad(mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_S_FIX)
370  || mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_X_FIX));
371  if (type == MLOG_1BYTE) {
372  return(mach_read_from_1(ptr));
373  } else if (type == MLOG_2BYTES) {
374  return(mach_read_from_2(ptr));
375  } else {
376  ut_ad(type == MLOG_4BYTES);
377  return(mach_read_from_4(ptr));
378  }
379 }
380 
381 #ifdef UNIV_DEBUG
382 # ifndef UNIV_HOTBACKUP
383 /**********************************************************/
386 UNIV_INTERN
387 ibool
388 mtr_memo_contains_page(
389 /*===================*/
390  mtr_t* mtr,
391  const byte* ptr,
392  ulint type)
393 {
394  return(mtr_memo_contains(mtr, buf_block_align(ptr), type));
395 }
396 
397 /*********************************************************/
399 UNIV_INTERN
400 void
401 mtr_print(
402 /*======*/
403  mtr_t* mtr)
404 {
405  fprintf(stderr,
406  "Mini-transaction handle: memo size %lu bytes"
407  " log size %lu bytes\n",
408  (ulong) dyn_array_get_data_size(&(mtr->memo)),
409  (ulong) dyn_array_get_data_size(&(mtr->log)));
410 }
411 # endif /* !UNIV_HOTBACKUP */
412 #endif /* UNIV_DEBUG */