~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

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