00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "mtr0mtr.h"
00027
00028 #ifdef UNIV_NONINL
00029 #include "mtr0mtr.ic"
00030 #endif
00031
00032 #include "buf0buf.h"
00033 #include "buf0flu.h"
00034 #include "page0types.h"
00035 #include "mtr0log.h"
00036 #include "log0log.h"
00037
00038 #ifndef UNIV_HOTBACKUP
00039 # include "log0recv.h"
00040
00042 static
00043 void
00044 mtr_memo_slot_release(
00045
00046 mtr_t* mtr,
00047 mtr_memo_slot_t* slot)
00048 {
00049 void* object;
00050 ulint type;
00051
00052 ut_ad(mtr);
00053 ut_ad(slot);
00054
00055 #ifndef UNIV_DEBUG
00056 UT_NOT_USED(mtr);
00057 #endif
00058
00059 object = slot->object;
00060 type = slot->type;
00061
00062 if (UNIV_LIKELY(object != NULL)) {
00063 if (type <= MTR_MEMO_BUF_FIX) {
00064 buf_page_release((buf_block_t*)object, type);
00065 } else if (type == MTR_MEMO_S_LOCK) {
00066 rw_lock_s_unlock((rw_lock_t*)object);
00067 #ifdef UNIV_DEBUG
00068 } else if (type != MTR_MEMO_X_LOCK) {
00069 ut_ad(type == MTR_MEMO_MODIFY);
00070 ut_ad(mtr_memo_contains(mtr, object,
00071 MTR_MEMO_PAGE_X_FIX));
00072 #endif
00073 } else {
00074 rw_lock_x_unlock((rw_lock_t*)object);
00075 }
00076 }
00077
00078 slot->object = NULL;
00079 }
00080
00081
00085 static
00086 void
00087 mtr_memo_pop_all(
00088
00089 mtr_t* mtr)
00090 {
00091 mtr_memo_slot_t* slot;
00092 dyn_array_t* memo;
00093 ulint offset;
00094
00095 ut_ad(mtr);
00096 ut_ad(mtr->magic_n == MTR_MAGIC_N);
00097 ut_ad(mtr->state == MTR_COMMITTING);
00098
00099 memo = &(mtr->memo);
00100
00101 offset = dyn_array_get_data_size(memo);
00102
00103 while (offset > 0) {
00104 offset -= sizeof(mtr_memo_slot_t);
00105 slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
00106
00107 mtr_memo_slot_release(mtr, slot);
00108 }
00109 }
00110
00111
00113 static
00114 void
00115 mtr_memo_slot_note_modification(
00116
00117 mtr_t* mtr,
00118 mtr_memo_slot_t* slot)
00119 {
00120 ut_ad(mtr);
00121 ut_ad(mtr->magic_n == MTR_MAGIC_N);
00122 ut_ad(mtr->modifications);
00123
00124 if (slot->object != NULL && slot->type == MTR_MEMO_PAGE_X_FIX) {
00125 buf_block_t* block = (buf_block_t*) slot->object;
00126
00127 #ifdef UNIV_DEBUG
00128 ut_ad(log_flush_order_mutex_own());
00129 #endif
00130 buf_flush_note_modification(block, mtr);
00131 }
00132 }
00133
00134
00141 static
00142 void
00143 mtr_memo_note_modifications(
00144
00145 mtr_t* mtr)
00146 {
00147 dyn_array_t* memo;
00148 ulint offset;
00149
00150 ut_ad(mtr);
00151 ut_ad(mtr->magic_n == MTR_MAGIC_N);
00152 ut_ad(mtr->state == MTR_COMMITTING);
00153
00154 memo = &mtr->memo;
00155
00156 offset = dyn_array_get_data_size(memo);
00157
00158 while (offset > 0) {
00159 mtr_memo_slot_t* slot;
00160
00161 offset -= sizeof(mtr_memo_slot_t);
00162 slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
00163
00164 mtr_memo_slot_note_modification(mtr, slot);
00165 }
00166 }
00167
00168
00170 static
00171 void
00172 mtr_log_reserve_and_write(
00173
00174 mtr_t* mtr)
00175 {
00176 dyn_array_t* mlog;
00177 dyn_block_t* block;
00178 ulint data_size;
00179 byte* first_data;
00180
00181 ut_ad(mtr);
00182
00183 mlog = &(mtr->log);
00184
00185 first_data = dyn_block_get_data(mlog);
00186
00187 if (mtr->n_log_recs > 1) {
00188 mlog_catenate_ulint(mtr, MLOG_MULTI_REC_END, MLOG_1BYTE);
00189 } else {
00190 *first_data = (byte)((ulint)*first_data
00191 | MLOG_SINGLE_REC_FLAG);
00192 }
00193
00194 if (mlog->heap == NULL) {
00195 mtr->end_lsn = log_reserve_and_write_fast(
00196 first_data, dyn_block_get_used(mlog),
00197 &mtr->start_lsn);
00198 if (mtr->end_lsn) {
00199
00200
00201
00202 goto func_exit;
00203 }
00204 }
00205
00206 data_size = dyn_array_get_data_size(mlog);
00207
00208
00209 mtr->start_lsn = log_reserve_and_open(data_size);
00210
00211 if (mtr->log_mode == MTR_LOG_ALL) {
00212
00213 block = mlog;
00214
00215 while (block != NULL) {
00216 log_write_low(dyn_block_get_data(block),
00217 dyn_block_get_used(block));
00218 block = dyn_array_get_next_block(mlog, block);
00219 }
00220 } else {
00221 ut_ad(mtr->log_mode == MTR_LOG_NONE);
00222
00223 }
00224
00225 mtr->end_lsn = log_close();
00226
00227 func_exit:
00228 log_flush_order_mutex_enter();
00229
00230
00231
00232
00233 log_release();
00234
00235 if (mtr->modifications) {
00236 mtr_memo_note_modifications(mtr);
00237 }
00238
00239 log_flush_order_mutex_exit();
00240 }
00241 #endif
00242
00243
00245 UNIV_INTERN
00246 void
00247 mtr_commit(
00248
00249 mtr_t* mtr)
00250 {
00251 ut_ad(mtr);
00252 ut_ad(mtr->magic_n == MTR_MAGIC_N);
00253 ut_ad(mtr->state == MTR_ACTIVE);
00254 ut_d(mtr->state = MTR_COMMITTING);
00255
00256 #ifndef UNIV_HOTBACKUP
00257
00258 ut_ad(!recv_no_log_write);
00259
00260 if (mtr->modifications && mtr->n_log_recs) {
00261 mtr_log_reserve_and_write(mtr);
00262 }
00263
00264 mtr_memo_pop_all(mtr);
00265 #endif
00266
00267 ut_d(mtr->state = MTR_COMMITTED);
00268 dyn_array_free(&(mtr->memo));
00269 dyn_array_free(&(mtr->log));
00270 }
00271
00272 #ifndef UNIV_HOTBACKUP
00273
00277 UNIV_INTERN
00278 void
00279 mtr_rollback_to_savepoint(
00280
00281 mtr_t* mtr,
00282 ulint savepoint)
00283 {
00284 mtr_memo_slot_t* slot;
00285 dyn_array_t* memo;
00286 ulint offset;
00287
00288 ut_ad(mtr);
00289 ut_ad(mtr->magic_n == MTR_MAGIC_N);
00290 ut_ad(mtr->state == MTR_ACTIVE);
00291
00292 memo = &(mtr->memo);
00293
00294 offset = dyn_array_get_data_size(memo);
00295 ut_ad(offset >= savepoint);
00296
00297 while (offset > savepoint) {
00298 offset -= sizeof(mtr_memo_slot_t);
00299
00300 slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
00301
00302 ut_ad(slot->type != MTR_MEMO_MODIFY);
00303
00304
00305
00306
00307 mtr_memo_slot_release(mtr, slot);
00308 }
00309 }
00310
00311
00313 UNIV_INTERN
00314 void
00315 mtr_memo_release(
00316
00317 mtr_t* mtr,
00318 void* object,
00319 ulint type)
00320 {
00321 mtr_memo_slot_t* slot;
00322 dyn_array_t* memo;
00323 ulint offset;
00324
00325 ut_ad(mtr);
00326 ut_ad(mtr->magic_n == MTR_MAGIC_N);
00327 ut_ad(mtr->state == MTR_ACTIVE);
00328
00329 memo = &(mtr->memo);
00330
00331 offset = dyn_array_get_data_size(memo);
00332
00333 log_flush_order_mutex_enter();
00334 while (offset > 0) {
00335 offset -= sizeof(mtr_memo_slot_t);
00336
00337 slot = static_cast<mtr_memo_slot_t *>(dyn_array_get_element(memo, offset));
00338
00339 if (object == slot->object && type == slot->type) {
00340
00341
00342
00343
00344 ut_ad(!(mtr->modifications
00345 && slot->type == MTR_MEMO_PAGE_X_FIX));
00346
00347 mtr_memo_slot_release(mtr, slot);
00348
00349 break;
00350 }
00351 }
00352 log_flush_order_mutex_exit();
00353 }
00354 #endif
00355
00356
00359 UNIV_INTERN
00360 ulint
00361 mtr_read_ulint(
00362
00363 const byte* ptr,
00364 ulint type,
00365 mtr_t* )
00367 {
00368 ut_ad(mtr->state == MTR_ACTIVE);
00369 ut_ad(mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_S_FIX)
00370 || mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_X_FIX));
00371 if (type == MLOG_1BYTE) {
00372 return(mach_read_from_1(ptr));
00373 } else if (type == MLOG_2BYTES) {
00374 return(mach_read_from_2(ptr));
00375 } else {
00376 ut_ad(type == MLOG_4BYTES);
00377 return(mach_read_from_4(ptr));
00378 }
00379 }
00380
00381 #ifdef UNIV_DEBUG
00382 # ifndef UNIV_HOTBACKUP
00383
00386 UNIV_INTERN
00387 ibool
00388 mtr_memo_contains_page(
00389
00390 mtr_t* mtr,
00391 const byte* ptr,
00392 ulint type)
00393 {
00394 return(mtr_memo_contains(mtr, buf_block_align(ptr), type));
00395 }
00396
00397
00399 UNIV_INTERN
00400 void
00401 mtr_print(
00402
00403 mtr_t* mtr)
00404 {
00405 fprintf(stderr,
00406 "Mini-transaction handle: memo size %lu bytes"
00407 " log size %lu bytes\n",
00408 (ulong) dyn_array_get_data_size(&(mtr->memo)),
00409 (ulong) dyn_array_get_data_size(&(mtr->log)));
00410 }
00411 # endif
00412 #endif