~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/mtr/mtr0mtr.c

Tags: innodb-plugin-1.0.1
Imported 1.0.1 with clean - with no changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
Mini-transaction buffer
 
3
 
 
4
(c) 1995 Innobase Oy
 
5
 
 
6
Created 11/26/1995 Heikki Tuuri
 
7
*******************************************************/
 
8
 
 
9
#include "mtr0mtr.h"
 
10
 
 
11
#ifdef UNIV_NONINL
 
12
#include "mtr0mtr.ic"
 
13
#endif
 
14
 
 
15
#include "buf0buf.h"
 
16
#include "page0types.h"
 
17
#include "mtr0log.h"
 
18
#include "log0log.h"
 
19
 
 
20
/*********************************************************************
 
21
Releases the item in the slot given. */
 
22
UNIV_INLINE
 
23
void
 
24
mtr_memo_slot_release(
 
25
/*==================*/
 
26
        mtr_t*                  mtr,    /* in: mtr */
 
27
        mtr_memo_slot_t*        slot)   /* in: memo slot */
 
28
{
 
29
        void*   object;
 
30
        ulint   type;
 
31
 
 
32
        ut_ad(mtr && slot);
 
33
 
 
34
        object = slot->object;
 
35
        type = slot->type;
 
36
 
 
37
        if (UNIV_LIKELY(object != NULL)) {
 
38
                if (type <= MTR_MEMO_BUF_FIX) {
 
39
                        buf_page_release((buf_block_t*)object, type, mtr);
 
40
                } else if (type == MTR_MEMO_S_LOCK) {
 
41
                        rw_lock_s_unlock((rw_lock_t*)object);
 
42
#ifdef UNIV_DEBUG
 
43
                } else if (type != MTR_MEMO_X_LOCK) {
 
44
                        ut_ad(type == MTR_MEMO_MODIFY);
 
45
                        ut_ad(mtr_memo_contains(mtr, object,
 
46
                                                MTR_MEMO_PAGE_X_FIX));
 
47
#endif /* UNIV_DEBUG */
 
48
                } else {
 
49
                        rw_lock_x_unlock((rw_lock_t*)object);
 
50
                }
 
51
        }
 
52
 
 
53
        slot->object = NULL;
 
54
}
 
55
 
 
56
/**************************************************************
 
57
Releases the mlocks and other objects stored in an mtr memo. They are released
 
58
in the order opposite to which they were pushed to the memo. NOTE! It is
 
59
essential that the x-rw-lock on a modified buffer page is not released before
 
60
buf_page_note_modification is called for that page! Otherwise, some thread
 
61
might race to modify it, and the flush list sort order on lsn would be
 
62
destroyed. */
 
63
UNIV_INLINE
 
64
void
 
65
mtr_memo_pop_all(
 
66
/*=============*/
 
67
        mtr_t*  mtr)    /* in: mtr */
 
68
{
 
69
        mtr_memo_slot_t* slot;
 
70
        dyn_array_t*    memo;
 
71
        ulint           offset;
 
72
 
 
73
        ut_ad(mtr);
 
74
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
75
        ut_ad(mtr->state == MTR_COMMITTING); /* Currently only used in
 
76
                                             commit */
 
77
        memo = &(mtr->memo);
 
78
 
 
79
        offset = dyn_array_get_data_size(memo);
 
80
 
 
81
        while (offset > 0) {
 
82
                offset -= sizeof(mtr_memo_slot_t);
 
83
                slot = dyn_array_get_element(memo, offset);
 
84
 
 
85
                mtr_memo_slot_release(mtr, slot);
 
86
        }
 
87
}
 
88
 
 
89
/****************************************************************
 
90
Writes the contents of a mini-transaction log, if any, to the database log. */
 
91
static
 
92
void
 
93
mtr_log_reserve_and_write(
 
94
/*======================*/
 
95
        mtr_t*  mtr)    /* in: mtr */
 
96
{
 
97
        dyn_array_t*    mlog;
 
98
        dyn_block_t*    block;
 
99
        ulint           data_size;
 
100
        ibool           success;
 
101
        byte*           first_data;
 
102
 
 
103
        ut_ad(mtr);
 
104
 
 
105
        mlog = &(mtr->log);
 
106
 
 
107
        first_data = dyn_block_get_data(mlog);
 
108
 
 
109
        if (mtr->n_log_recs > 1) {
 
110
                mlog_catenate_ulint(mtr, MLOG_MULTI_REC_END, MLOG_1BYTE);
 
111
        } else {
 
112
                *first_data = (byte)((ulint)*first_data
 
113
                                     | MLOG_SINGLE_REC_FLAG);
 
114
        }
 
115
 
 
116
        if (mlog->heap == NULL) {
 
117
                mtr->end_lsn = log_reserve_and_write_fast(
 
118
                        first_data, dyn_block_get_used(mlog),
 
119
                        &(mtr->start_lsn), &success);
 
120
                if (success) {
 
121
 
 
122
                        return;
 
123
                }
 
124
        }
 
125
 
 
126
        data_size = dyn_array_get_data_size(mlog);
 
127
 
 
128
        /* Open the database log for log_write_low */
 
129
        mtr->start_lsn = log_reserve_and_open(data_size);
 
130
 
 
131
        if (mtr->log_mode == MTR_LOG_ALL) {
 
132
 
 
133
                block = mlog;
 
134
 
 
135
                while (block != NULL) {
 
136
                        log_write_low(dyn_block_get_data(block),
 
137
                                      dyn_block_get_used(block));
 
138
                        block = dyn_array_get_next_block(mlog, block);
 
139
                }
 
140
        } else {
 
141
                ut_ad(mtr->log_mode == MTR_LOG_NONE);
 
142
                /* Do nothing */
 
143
        }
 
144
 
 
145
        mtr->end_lsn = log_close();
 
146
}
 
147
 
 
148
/*******************************************************************
 
149
Commits a mini-transaction. */
 
150
UNIV_INTERN
 
151
void
 
152
mtr_commit(
 
153
/*=======*/
 
154
        mtr_t*  mtr)    /* in: mini-transaction */
 
155
{
 
156
        ibool           write_log;
 
157
 
 
158
        ut_ad(mtr);
 
159
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
160
        ut_ad(mtr->state == MTR_ACTIVE);
 
161
#ifdef UNIV_DEBUG
 
162
        mtr->state = MTR_COMMITTING;
 
163
#endif
 
164
        write_log = mtr->modifications && mtr->n_log_recs;
 
165
 
 
166
        if (write_log) {
 
167
                mtr_log_reserve_and_write(mtr);
 
168
        }
 
169
 
 
170
        /* We first update the modification info to buffer pages, and only
 
171
        after that release the log mutex: this guarantees that when the log
 
172
        mutex is free, all buffer pages contain an up-to-date info of their
 
173
        modifications. This fact is used in making a checkpoint when we look
 
174
        at the oldest modification of any page in the buffer pool. It is also
 
175
        required when we insert modified buffer pages in to the flush list
 
176
        which must be sorted on oldest_modification. */
 
177
 
 
178
        mtr_memo_pop_all(mtr);
 
179
 
 
180
        if (write_log) {
 
181
                log_release();
 
182
        }
 
183
 
 
184
#ifdef UNIV_DEBUG
 
185
        mtr->state = MTR_COMMITTED;
 
186
#endif
 
187
        dyn_array_free(&(mtr->memo));
 
188
        dyn_array_free(&(mtr->log));
 
189
}
 
190
 
 
191
/**************************************************************
 
192
Releases the latches stored in an mtr memo down to a savepoint.
 
193
NOTE! The mtr must not have made changes to buffer pages after the
 
194
savepoint, as these can be handled only by mtr_commit. */
 
195
UNIV_INTERN
 
196
void
 
197
mtr_rollback_to_savepoint(
 
198
/*======================*/
 
199
        mtr_t*  mtr,            /* in: mtr */
 
200
        ulint   savepoint)      /* in: savepoint */
 
201
{
 
202
        mtr_memo_slot_t* slot;
 
203
        dyn_array_t*    memo;
 
204
        ulint           offset;
 
205
 
 
206
        ut_ad(mtr);
 
207
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
208
        ut_ad(mtr->state == MTR_ACTIVE);
 
209
 
 
210
        memo = &(mtr->memo);
 
211
 
 
212
        offset = dyn_array_get_data_size(memo);
 
213
        ut_ad(offset >= savepoint);
 
214
 
 
215
        while (offset > savepoint) {
 
216
                offset -= sizeof(mtr_memo_slot_t);
 
217
 
 
218
                slot = dyn_array_get_element(memo, offset);
 
219
 
 
220
                ut_ad(slot->type != MTR_MEMO_MODIFY);
 
221
                mtr_memo_slot_release(mtr, slot);
 
222
        }
 
223
}
 
224
 
 
225
/*******************************************************
 
226
Releases an object in the memo stack. */
 
227
UNIV_INTERN
 
228
void
 
229
mtr_memo_release(
 
230
/*=============*/
 
231
        mtr_t*  mtr,    /* in: mtr */
 
232
        void*   object, /* in: object */
 
233
        ulint   type)   /* in: object type: MTR_MEMO_S_LOCK, ... */
 
234
{
 
235
        mtr_memo_slot_t* slot;
 
236
        dyn_array_t*    memo;
 
237
        ulint           offset;
 
238
 
 
239
        ut_ad(mtr);
 
240
        ut_ad(mtr->magic_n == MTR_MAGIC_N);
 
241
        ut_ad(mtr->state == MTR_ACTIVE);
 
242
 
 
243
        memo = &(mtr->memo);
 
244
 
 
245
        offset = dyn_array_get_data_size(memo);
 
246
 
 
247
        while (offset > 0) {
 
248
                offset -= sizeof(mtr_memo_slot_t);
 
249
 
 
250
                slot = dyn_array_get_element(memo, offset);
 
251
 
 
252
                if ((object == slot->object) && (type == slot->type)) {
 
253
 
 
254
                        mtr_memo_slot_release(mtr, slot);
 
255
 
 
256
                        break;
 
257
                }
 
258
        }
 
259
}
 
260
 
 
261
/************************************************************
 
262
Reads 1 - 4 bytes from a file page buffered in the buffer pool. */
 
263
UNIV_INTERN
 
264
ulint
 
265
mtr_read_ulint(
 
266
/*===========*/
 
267
                                /* out: value read */
 
268
        const byte*     ptr,    /* in: pointer from where to read */
 
269
        ulint           type,   /* in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
 
270
        mtr_t*          mtr __attribute__((unused)))
 
271
                                /* in: mini-transaction handle */
 
272
{
 
273
        ut_ad(mtr->state == MTR_ACTIVE);
 
274
        ut_ad(mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_S_FIX)
 
275
              || mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_X_FIX));
 
276
        if (type == MLOG_1BYTE) {
 
277
                return(mach_read_from_1(ptr));
 
278
        } else if (type == MLOG_2BYTES) {
 
279
                return(mach_read_from_2(ptr));
 
280
        } else {
 
281
                ut_ad(type == MLOG_4BYTES);
 
282
                return(mach_read_from_4(ptr));
 
283
        }
 
284
}
 
285
 
 
286
/************************************************************
 
287
Reads 8 bytes from a file page buffered in the buffer pool. */
 
288
UNIV_INTERN
 
289
dulint
 
290
mtr_read_dulint(
 
291
/*============*/
 
292
                                /* out: value read */
 
293
        const byte*     ptr,    /* in: pointer from where to read */
 
294
        mtr_t*          mtr __attribute__((unused)))
 
295
                                /* in: mini-transaction handle */
 
296
{
 
297
        ut_ad(mtr->state == MTR_ACTIVE);
 
298
        ut_ad(mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_S_FIX)
 
299
              || mtr_memo_contains_page(mtr, ptr, MTR_MEMO_PAGE_X_FIX));
 
300
        return(mach_read_from_8(ptr));
 
301
}
 
302
 
 
303
#ifdef UNIV_DEBUG
 
304
/**************************************************************
 
305
Checks if memo contains the given page. */
 
306
UNIV_INTERN
 
307
ibool
 
308
mtr_memo_contains_page(
 
309
/*===================*/
 
310
                                /* out: TRUE if contains */
 
311
        mtr_t*          mtr,    /* in: mtr */
 
312
        const byte*     ptr,    /* in: pointer to buffer frame */
 
313
        ulint           type)   /* in: type of object */
 
314
{
 
315
        ibool   ret;
 
316
 
 
317
        buf_pool_mutex_enter();
 
318
        ret = mtr_memo_contains(mtr, buf_block_align(ptr), type);
 
319
        buf_pool_mutex_exit();
 
320
        return(ret);
 
321
}
 
322
 
 
323
/*************************************************************
 
324
Prints info of an mtr handle. */
 
325
UNIV_INTERN
 
326
void
 
327
mtr_print(
 
328
/*======*/
 
329
        mtr_t*  mtr)    /* in: mtr */
 
330
{
 
331
        fprintf(stderr,
 
332
                "Mini-transaction handle: memo size %lu bytes"
 
333
                " log size %lu bytes\n",
 
334
                (ulong) dyn_array_get_data_size(&(mtr->memo)),
 
335
                (ulong) dyn_array_get_data_size(&(mtr->log)));
 
336
}
 
337
#endif /* UNIV_DEBUG */