~drizzle-trunk/drizzle/development

641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1
/*****************************************************************************
2
3
Copyright (c) 1997, 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
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
16
17
*****************************************************************************/
18
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
19
/**************************************************//**
20
@file include/ibuf0ibuf.ic
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
21
Insert buffer
22
23
Created 7/19/1997 Heikki Tuuri
24
*******************************************************/
25
26
#include "page0page.h"
27
#include "page0zip.h"
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
28
#ifndef UNIV_HOTBACKUP
29
#include "buf0lru.h"
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
30
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
31
/** Counter for ibuf_should_try() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
32
extern ulint	ibuf_flush_count;
33
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
34
/** An index page must contain at least UNIV_PAGE_SIZE /
35
IBUF_PAGE_SIZE_PER_FREE_SPACE bytes of free space for ibuf to try to
36
buffer inserts to this page.  If there is this much of free space, the
37
corresponding bits are set in the ibuf bitmap. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
38
#define IBUF_PAGE_SIZE_PER_FREE_SPACE	32
39
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
40
/** Insert buffer struct */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
41
struct ibuf_struct{
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
42
	ulint		size;		/*!< current size of the ibuf index
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
43
					tree, in pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
44
	ulint		max_size;	/*!< recommended maximum size of the
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
45
					ibuf index tree, in pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
46
	ulint		seg_size;	/*!< allocated pages of the file
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
47
					segment containing ibuf header and
48
					tree */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
49
	ibool		empty;		/*!< after an insert to the ibuf tree
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
50
					is performed, this is set to FALSE,
51
					and if a contract operation finds
52
					the tree empty, this is set to
53
					TRUE */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
54
	ulint		free_list_len;	/*!< length of the free list */
55
	ulint		height;		/*!< tree height */
56
	dict_index_t*	index;		/*!< insert buffer index */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
57
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
58
	ulint		n_merges;	/*!< number of pages merged */
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
59
	ulint		n_merged_ops[IBUF_OP_COUNT];
60
					/*!< number of operations of each type
61
					merged to index pages */
62
	ulint		n_discarded_ops[IBUF_OP_COUNT];
63
					/*!< number of operations of each type
64
					discarded without merging due to the
65
					tablespace being deleted or the
66
					index being dropped */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
67
};
68
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
69
/************************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
70
Sets the free bit of the page in the ibuf bitmap. This is done in a separate
71
mini-transaction, hence this operation does not restrict further work to only
72
ibuf bitmap operations, which would result if the latch to the bitmap page
73
were kept. */
74
UNIV_INTERN
75
void
76
ibuf_set_free_bits_func(
77
/*====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
78
	buf_block_t*	block,	/*!< in: index page of a non-clustered index;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
79
				free bit is reset if page level is 0 */
80
#ifdef UNIV_IBUF_DEBUG
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
81
	ulint		max_val,/*!< in: ULINT_UNDEFINED or a maximum
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
82
				value which the bits must have before
83
				setting; this is for debugging */
84
#endif /* UNIV_IBUF_DEBUG */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
85
	ulint		val);	/*!< in: value to set: < 4 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
86
#ifdef UNIV_IBUF_DEBUG
87
# define ibuf_set_free_bits(b,v,max) ibuf_set_free_bits_func(b,max,v)
88
#else /* UNIV_IBUF_DEBUG */
89
# define ibuf_set_free_bits(b,v,max) ibuf_set_free_bits_func(b,v)
90
#endif /* UNIV_IBUF_DEBUG */
91
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
92
/**********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
93
A basic partial test if an insert to the insert buffer could be possible and
94
recommended. */
95
UNIV_INLINE
96
ibool
97
ibuf_should_try(
98
/*============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
99
	dict_index_t*	index,			/*!< in: index where to insert */
100
	ulint		ignore_sec_unique)	/*!< in: if != 0, we should
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
101
						ignore UNIQUE constraint on
102
						a secondary index when we
103
						decide */
104
{
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
105
	if (ibuf_use != IBUF_USE_NONE
106
	    && !dict_index_is_clust(index)
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
107
	    && (ignore_sec_unique || !dict_index_is_unique(index))) {
108
109
		ibuf_flush_count++;
110
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
111
		if (ibuf_flush_count % 4 == 0) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
112
1819.7.68 by Stewart Smith
Merge initial InnoDB+ import.
113
			buf_LRU_try_free_flushed_blocks(NULL);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
114
		}
115
116
		return(TRUE);
117
	}
118
119
	return(FALSE);
120
}
121
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
122
/***********************************************************************//**
123
Checks if a page address is an ibuf bitmap page address.
124
@return	TRUE if a bitmap page */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
125
UNIV_INLINE
126
ibool
127
ibuf_bitmap_page(
128
/*=============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
129
	ulint	zip_size,/*!< in: compressed page size in bytes;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
130
			0 for uncompressed pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
131
	ulint	page_no)/*!< in: page number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
132
{
133
	ut_ad(ut_is_2pow(zip_size));
134
135
	if (!zip_size) {
136
		return(UNIV_UNLIKELY((page_no & (UNIV_PAGE_SIZE - 1))
137
				     == FSP_IBUF_BITMAP_OFFSET));
138
	}
139
140
	return(UNIV_UNLIKELY((page_no & (zip_size - 1))
141
			     == FSP_IBUF_BITMAP_OFFSET));
142
}
143
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
144
/*********************************************************************//**
145
Translates the free space on a page to a value in the ibuf bitmap.
146
@return	value for ibuf bitmap bits */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
147
UNIV_INLINE
148
ulint
149
ibuf_index_page_calc_free_bits(
150
/*===========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
151
	ulint	zip_size,	/*!< in: compressed page size in bytes;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
152
				0 for uncompressed pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
153
	ulint	max_ins_size)	/*!< in: maximum insert size after reorganize
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
154
				for the page */
155
{
156
	ulint	n;
157
	ut_ad(ut_is_2pow(zip_size));
158
	ut_ad(!zip_size || zip_size > IBUF_PAGE_SIZE_PER_FREE_SPACE);
159
	ut_ad(zip_size <= UNIV_PAGE_SIZE);
160
161
	if (zip_size) {
162
		n = max_ins_size
163
			/ (zip_size / IBUF_PAGE_SIZE_PER_FREE_SPACE);
164
	} else {
165
		n = max_ins_size
166
			/ (UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE);
167
	}
168
169
	if (n == 3) {
170
		n = 2;
171
	}
172
173
	if (n > 3) {
174
		n = 3;
175
	}
176
177
	return(n);
178
}
179
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
180
/*********************************************************************//**
181
Translates the ibuf free bits to the free space on a page in bytes.
182
@return	maximum insert size after reorganize for the page */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
183
UNIV_INLINE
184
ulint
185
ibuf_index_page_calc_free_from_bits(
186
/*================================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
187
	ulint	zip_size,/*!< in: compressed page size in bytes;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
188
			0 for uncompressed pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
189
	ulint	bits)	/*!< in: value for ibuf bitmap bits */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
190
{
191
	ut_ad(bits < 4);
192
	ut_ad(ut_is_2pow(zip_size));
193
	ut_ad(!zip_size || zip_size > IBUF_PAGE_SIZE_PER_FREE_SPACE);
194
	ut_ad(zip_size <= UNIV_PAGE_SIZE);
195
196
	if (zip_size) {
197
		if (bits == 3) {
198
			return(4 * zip_size / IBUF_PAGE_SIZE_PER_FREE_SPACE);
199
		}
200
201
		return(bits * zip_size / IBUF_PAGE_SIZE_PER_FREE_SPACE);
202
	}
203
204
	if (bits == 3) {
205
		return(4 * UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE);
206
	}
207
208
	return(bits * (UNIV_PAGE_SIZE / IBUF_PAGE_SIZE_PER_FREE_SPACE));
209
}
210
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
211
/*********************************************************************//**
212
Translates the free space on a compressed page to a value in the ibuf bitmap.
213
@return	value for ibuf bitmap bits */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
214
UNIV_INLINE
215
ulint
216
ibuf_index_page_calc_free_zip(
217
/*==========================*/
218
	ulint			zip_size,
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
219
					/*!< in: compressed page size in bytes */
220
	const buf_block_t*	block)	/*!< in: buffer block */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
221
{
222
	ulint			max_ins_size;
223
	const page_zip_des_t*	page_zip;
224
	lint			zip_max_ins;
225
226
	ut_ad(zip_size == buf_block_get_zip_size(block));
227
	ut_ad(zip_size);
228
229
	max_ins_size = page_get_max_insert_size_after_reorganize(
230
		buf_block_get_frame(block), 1);
231
232
	page_zip = buf_block_get_page_zip(block);
233
	zip_max_ins = page_zip_max_ins_size(page_zip,
234
					    FALSE/* not clustered */);
235
236
	if (UNIV_UNLIKELY(zip_max_ins < 0)) {
237
		return(0);
238
	} else if (UNIV_LIKELY(max_ins_size > (ulint) zip_max_ins)) {
239
		max_ins_size = (ulint) zip_max_ins;
240
	}
241
242
	return(ibuf_index_page_calc_free_bits(zip_size, max_ins_size));
243
}
244
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
245
/*********************************************************************//**
246
Translates the free space on a page to a value in the ibuf bitmap.
247
@return	value for ibuf bitmap bits */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
248
UNIV_INLINE
249
ulint
250
ibuf_index_page_calc_free(
251
/*======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
252
	ulint			zip_size,/*!< in: compressed page size in bytes;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
253
					0 for uncompressed pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
254
	const buf_block_t*	block)	/*!< in: buffer block */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
255
{
256
	ut_ad(zip_size == buf_block_get_zip_size(block));
257
258
	if (!zip_size) {
259
		ulint	max_ins_size;
260
261
		max_ins_size = page_get_max_insert_size_after_reorganize(
262
			buf_block_get_frame(block), 1);
263
264
		return(ibuf_index_page_calc_free_bits(0, max_ins_size));
265
	} else {
266
		return(ibuf_index_page_calc_free_zip(zip_size, block));
267
	}
268
}
269
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
270
/************************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
271
Updates the free bits of an uncompressed page in the ibuf bitmap if
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
272
there is not enough free on the page any more.  This is done in a
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
273
separate mini-transaction, hence this operation does not restrict
274
further work to only ibuf bitmap operations, which would result if the
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
275
latch to the bitmap page were kept.  NOTE: The free bits in the insert
276
buffer bitmap must never exceed the free space on a page.  It is
277
unsafe to increment the bits in a separately committed
278
mini-transaction, because in crash recovery, the free bits could
279
momentarily be set too high.  It is only safe to use this function for
280
decrementing the free bits.  Should more free space become available,
281
we must not update the free bits here, because that would break crash
282
recovery. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
283
UNIV_INLINE
284
void
285
ibuf_update_free_bits_if_full(
286
/*==========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
287
	buf_block_t*	block,	/*!< in: index page to which we have added new
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
288
				records; the free bits are updated if the
289
				index is non-clustered and non-unique and
290
				the page level is 0, and the page becomes
291
				fuller */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
292
	ulint		max_ins_size,/*!< in: value of maximum insert size with
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
293
				reorganize before the latest operation
294
				performed to the page */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
295
	ulint		increase)/*!< in: upper limit for the additional space
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
296
				used in the latest operation, if known, or
297
				ULINT_UNDEFINED */
298
{
299
	ulint	before;
300
	ulint	after;
301
302
	ut_ad(!buf_block_get_page_zip(block));
303
304
	before = ibuf_index_page_calc_free_bits(0, max_ins_size);
305
306
	if (max_ins_size >= increase) {
307
#if ULINT32_UNDEFINED <= UNIV_PAGE_SIZE
308
# error "ULINT32_UNDEFINED <= UNIV_PAGE_SIZE"
309
#endif
310
		after = ibuf_index_page_calc_free_bits(0, max_ins_size
311
						       - increase);
312
#ifdef UNIV_IBUF_DEBUG
313
		ut_a(after <= ibuf_index_page_calc_free(0, block));
314
#endif
315
	} else {
316
		after = ibuf_index_page_calc_free(0, block);
317
	}
318
319
	if (after == 0) {
320
		/* We move the page to the front of the buffer pool LRU list:
321
		the purpose of this is to prevent those pages to which we
322
		cannot make inserts using the insert buffer from slipping
323
		out of the buffer pool */
324
325
		buf_page_make_young(&block->page);
326
	}
327
328
	if (before > after) {
329
		ibuf_set_free_bits(block, after, before);
330
	}
331
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
332
#endif /* !UNIV_HOTBACKUP */