~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 ibuf/ibuf0ibuf.c
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 "ibuf0ibuf.h"
27
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
28
/** Number of bits describing a single page */
29
#define IBUF_BITS_PER_PAGE	4
30
#if IBUF_BITS_PER_PAGE % 2
31
# error "IBUF_BITS_PER_PAGE must be an even number!"
32
#endif
33
/** The start address for an insert buffer bitmap page bitmap */
34
#define IBUF_BITMAP		PAGE_DATA
35
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
36
#ifdef UNIV_NONINL
37
#include "ibuf0ibuf.ic"
38
#endif
39
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
40
#ifndef UNIV_HOTBACKUP
41
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
42
#include "buf0buf.h"
43
#include "buf0rea.h"
44
#include "fsp0fsp.h"
45
#include "trx0sys.h"
46
#include "fil0fil.h"
47
#include "thr0loc.h"
48
#include "rem0rec.h"
49
#include "btr0cur.h"
50
#include "btr0pcur.h"
51
#include "btr0btr.h"
52
#include "sync0sync.h"
53
#include "dict0boot.h"
54
#include "fut0lst.h"
55
#include "lock0lock.h"
56
#include "log0recv.h"
57
#include "que0que.h"
58
59
/*	STRUCTURE OF AN INSERT BUFFER RECORD
60
61
In versions < 4.1.x:
62
63
1. The first field is the page number.
64
2. The second field is an array which stores type info for each subsequent
65
   field. We store the information which affects the ordering of records, and
66
   also the physical storage size of an SQL NULL value. E.g., for CHAR(10) it
67
   is 10 bytes.
68
3. Next we have the fields of the actual index record.
69
70
In versions >= 4.1.x:
71
72
Note that contary to what we planned in the 1990's, there will only be one
73
insert buffer tree, and that is in the system tablespace of InnoDB.
74
75
1. The first field is the space id.
76
2. The second field is a one-byte marker (0) which differentiates records from
77
   the < 4.1.x storage format.
78
3. The third field is the page number.
79
4. The fourth field contains the type info, where we have also added 2 bytes to
80
   store the charset. In the compressed table format of 5.0.x we must add more
81
   information here so that we can build a dummy 'index' struct which 5.0.x
82
   can use in the binary search on the index page in the ibuf merge phase.
83
5. The rest of the fields contain the fields of the actual index record.
84
85
In versions >= 5.0.3:
86
87
The first byte of the fourth field is an additional marker (0) if the record
88
is in the compact format.  The presence of this marker can be detected by
89
looking at the length of the field modulo DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE.
90
91
The high-order bit of the character set field in the type info is the
92
"nullable" flag for the field. */
93
94
95
/*	PREVENTING DEADLOCKS IN THE INSERT BUFFER SYSTEM
96
97
If an OS thread performs any operation that brings in disk pages from
98
non-system tablespaces into the buffer pool, or creates such a page there,
99
then the operation may have as a side effect an insert buffer index tree
100
compression. Thus, the tree latch of the insert buffer tree may be acquired
101
in the x-mode, and also the file space latch of the system tablespace may
102
be acquired in the x-mode.
103
104
Also, an insert to an index in a non-system tablespace can have the same
105
effect. How do we know this cannot lead to a deadlock of OS threads? There
106
is a problem with the i\o-handler threads: they break the latching order
107
because they own x-latches to pages which are on a lower level than the
108
insert buffer tree latch, its page latches, and the tablespace latch an
109
insert buffer operation can reserve.
110
111
The solution is the following: Let all the tree and page latches connected
112
with the insert buffer be later in the latching order than the fsp latch and
113
fsp page latches.
114
115
Insert buffer pages must be such that the insert buffer is never invoked
116
when these pages are accessed as this would result in a recursion violating
117
the latching order. We let a special i/o-handler thread take care of i/o to
118
the insert buffer pages and the ibuf bitmap pages, as well as the fsp bitmap
119
pages and the first inode page, which contains the inode of the ibuf tree: let
120
us call all these ibuf pages. To prevent deadlocks, we do not let a read-ahead
121
access both non-ibuf and ibuf pages.
122
123
Then an i/o-handler for the insert buffer never needs to access recursively the
124
insert buffer tree and thus obeys the latching order. On the other hand, other
125
i/o-handlers for other tablespaces may require access to the insert buffer,
126
but because all kinds of latches they need to access there are later in the
127
latching order, no violation of the latching order occurs in this case,
128
either.
129
130
A problem is how to grow and contract an insert buffer tree. As it is later
131
in the latching order than the fsp management, we have to reserve the fsp
132
latch first, before adding or removing pages from the insert buffer tree.
133
We let the insert buffer tree have its own file space management: a free
134
list of pages linked to the tree root. To prevent recursive using of the
135
insert buffer when adding pages to the tree, we must first load these pages
136
to memory, obtaining a latch on them, and only after that add them to the
137
free list of the insert buffer tree. More difficult is removing of pages
138
from the free list. If there is an excess of pages in the free list of the
139
ibuf tree, they might be needed if some thread reserves the fsp latch,
140
intending to allocate more file space. So we do the following: if a thread
141
reserves the fsp latch, we check the writer count field of the latch. If
142
this field has value 1, it means that the thread did not own the latch
143
before entering the fsp system, and the mtr of the thread contains no
144
modifications to the fsp pages. Now we are free to reserve the ibuf latch,
145
and check if there is an excess of pages in the free list. We can then, in a
146
separate mini-transaction, take them out of the free list and free them to
147
the fsp system.
148
149
To avoid deadlocks in the ibuf system, we divide file pages into three levels:
150
151
(1) non-ibuf pages,
152
(2) ibuf tree pages and the pages in the ibuf tree free list, and
153
(3) ibuf bitmap pages.
154
155
No OS thread is allowed to access higher level pages if it has latches to
156
lower level pages; even if the thread owns a B-tree latch it must not access
157
the B-tree non-leaf pages if it has latches on lower level pages. Read-ahead
158
is only allowed for level 1 and 2 pages. Dedicated i/o-handler threads handle
159
exclusively level 1 i/o. A dedicated i/o handler thread handles exclusively
160
level 2 i/o. However, if an OS thread does the i/o handling for itself, i.e.,
161
it uses synchronous aio, it can access any pages, as long as it obeys the
162
access order rules. */
163
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
164
/** Buffer pool size per the maximum insert buffer size */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
165
#define IBUF_POOL_SIZE_PER_MAX_SIZE	2
166
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
167
/** Table name for the insert buffer. */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
168
#define IBUF_TABLE_NAME		"SYS_IBUF_TABLE"
169
170
/** Operations that can currently be buffered. */
171
UNIV_INTERN ibuf_use_t	ibuf_use		= IBUF_USE_INSERT;
172
173
/** The insert buffer control structure */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
174
UNIV_INTERN ibuf_t*	ibuf			= NULL;
175
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
176
/** Counter for ibuf_should_try() */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
177
UNIV_INTERN ulint	ibuf_flush_count	= 0;
178
179
#ifdef UNIV_IBUF_COUNT_DEBUG
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
180
/** Number of tablespaces in the ibuf_counts array */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
181
#define IBUF_COUNT_N_SPACES	4
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
182
/** Number of pages within each tablespace in the ibuf_counts array */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
183
#define IBUF_COUNT_N_PAGES	130000
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
184
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
185
/** Buffered entry counts for file pages, used in debugging */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
186
static ulint	ibuf_counts[IBUF_COUNT_N_SPACES][IBUF_COUNT_N_PAGES];
187
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
188
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
189
Checks that the indexes to ibuf_counts[][] are within limits. */
190
UNIV_INLINE
191
void
192
ibuf_count_check(
193
/*=============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
194
	ulint	space_id,	/*!< in: space identifier */
195
	ulint	page_no)	/*!< in: page number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
196
{
197
	if (space_id < IBUF_COUNT_N_SPACES && page_no < IBUF_COUNT_N_PAGES) {
198
		return;
199
	}
200
201
	fprintf(stderr,
202
		"InnoDB: UNIV_IBUF_COUNT_DEBUG limits space_id and page_no\n"
203
		"InnoDB: and breaks crash recovery.\n"
204
		"InnoDB: space_id=%lu, should be 0<=space_id<%lu\n"
205
		"InnoDB: page_no=%lu, should be 0<=page_no<%lu\n",
206
		(ulint) space_id, (ulint) IBUF_COUNT_N_SPACES,
207
		(ulint) page_no, (ulint) IBUF_COUNT_N_PAGES);
208
	ut_error;
209
}
210
#endif
211
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
212
/** @name Offsets to the per-page bits in the insert buffer bitmap */
213
/* @{ */
214
#define	IBUF_BITMAP_FREE	0	/*!< Bits indicating the
215
					amount of free space */
216
#define IBUF_BITMAP_BUFFERED	2	/*!< TRUE if there are buffered
217
					changes for the page */
218
#define IBUF_BITMAP_IBUF	3	/*!< TRUE if page is a part of
219
					the ibuf tree, excluding the
220
					root page, or is in the free
221
					list of the ibuf */
222
/* @} */
223
224
/** The mutex used to block pessimistic inserts to ibuf trees */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
225
static mutex_t	ibuf_pessimistic_insert_mutex;
226
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
227
/** The mutex protecting the insert buffer structs */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
228
static mutex_t	ibuf_mutex;
229
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
230
/** The mutex protecting the insert buffer bitmaps */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
231
static mutex_t	ibuf_bitmap_mutex;
232
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
233
/** The area in pages from which contract looks for page numbers for merge */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
234
#define	IBUF_MERGE_AREA			8
235
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
236
/** Inside the merge area, pages which have at most 1 per this number less
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
237
buffered entries compared to maximum volume that can buffered for a single
238
page are merged along with the page whose buffer became full */
239
#define IBUF_MERGE_THRESHOLD		4
240
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
241
/** In ibuf_contract at most this number of pages is read to memory in one
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
242
batch, in order to merge the entries for them in the insert buffer */
243
#define	IBUF_MAX_N_PAGES_MERGED		IBUF_MERGE_AREA
244
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
245
/** If the combined size of the ibuf trees exceeds ibuf->max_size by this
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
246
many pages, we start to contract it in connection to inserts there, using
247
non-synchronous contract */
248
#define IBUF_CONTRACT_ON_INSERT_NON_SYNC	0
249
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
250
/** If the combined size of the ibuf trees exceeds ibuf->max_size by this
251
many pages, we start to contract it in connection to inserts there, using
252
synchronous contract */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
253
#define IBUF_CONTRACT_ON_INSERT_SYNC		5
254
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
255
/** If the combined size of the ibuf trees exceeds ibuf->max_size by
256
this many pages, we start to contract it synchronous contract, but do
257
not insert */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
258
#define IBUF_CONTRACT_DO_NOT_INSERT		10
259
260
/* TODO: how to cope with drop table if there are records in the insert
261
buffer for the indexes of the table? Is there actually any problem,
262
because ibuf merge is done to a page when it is read in, and it is
263
still physically like the index page even if the index would have been
264
dropped! So, there seems to be no problem. */
265
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
266
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
267
Sets the flag in the current OS thread local storage denoting that it is
268
inside an insert buffer routine. */
269
UNIV_INLINE
270
void
271
ibuf_enter(void)
272
/*============*/
273
{
274
	ibool*	ptr;
275
276
	ptr = thr_local_get_in_ibuf_field();
277
278
	ut_ad(*ptr == FALSE);
279
280
	*ptr = TRUE;
281
}
282
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
283
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
284
Sets the flag in the current OS thread local storage denoting that it is
285
exiting an insert buffer routine. */
286
UNIV_INLINE
287
void
288
ibuf_exit(void)
289
/*===========*/
290
{
291
	ibool*	ptr;
292
293
	ptr = thr_local_get_in_ibuf_field();
294
295
	ut_ad(*ptr == TRUE);
296
297
	*ptr = FALSE;
298
}
299
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
300
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
301
Returns TRUE if the current OS thread is performing an insert buffer
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
302
routine.
303
304
For instance, a read-ahead of non-ibuf pages is forbidden by threads
305
that are executing an insert buffer routine.
306
@return TRUE if inside an insert buffer routine */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
307
UNIV_INTERN
308
ibool
309
ibuf_inside(void)
310
/*=============*/
311
{
312
	return(*thr_local_get_in_ibuf_field());
313
}
314
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
315
/******************************************************************//**
316
Gets the ibuf header page and x-latches it.
317
@return	insert buffer header page */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
318
static
319
page_t*
320
ibuf_header_page_get(
321
/*=================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
322
	mtr_t*	mtr)	/*!< in: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
323
{
324
	buf_block_t*	block;
325
326
	ut_ad(!ibuf_inside());
327
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
328
	block = buf_page_get(
329
		IBUF_SPACE_ID, 0, FSP_IBUF_HEADER_PAGE_NO, RW_X_LATCH, mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
330
	buf_block_dbg_add_level(block, SYNC_IBUF_HEADER);
331
332
	return(buf_block_get_frame(block));
333
}
334
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
335
/******************************************************************//**
336
Gets the root page and x-latches it.
337
@return	insert buffer tree root page */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
338
static
339
page_t*
340
ibuf_tree_root_get(
341
/*===============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
342
	mtr_t*		mtr)	/*!< in: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
343
{
344
	buf_block_t*	block;
345
346
	ut_ad(ibuf_inside());
347
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
348
	mtr_x_lock(dict_index_get_lock(ibuf->index), mtr);
349
350
	block = buf_page_get(
351
		IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, mtr);
352
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
353
	buf_block_dbg_add_level(block, SYNC_TREE_NODE);
354
355
	return(buf_block_get_frame(block));
356
}
357
358
#ifdef UNIV_IBUF_COUNT_DEBUG
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
359
/******************************************************************//**
360
Gets the ibuf count for a given page.
361
@return number of entries in the insert buffer currently buffered for
362
this page */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
363
UNIV_INTERN
364
ulint
365
ibuf_count_get(
366
/*===========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
367
	ulint	space,	/*!< in: space id */
368
	ulint	page_no)/*!< in: page number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
369
{
370
	ibuf_count_check(space, page_no);
371
372
	return(ibuf_counts[space][page_no]);
373
}
374
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
375
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
376
Sets the ibuf count for a given page. */
377
static
378
void
379
ibuf_count_set(
380
/*===========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
381
	ulint	space,	/*!< in: space id */
382
	ulint	page_no,/*!< in: page number */
383
	ulint	val)	/*!< in: value to set */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
384
{
385
	ibuf_count_check(space, page_no);
386
	ut_a(val < UNIV_PAGE_SIZE);
387
388
	ibuf_counts[space][page_no] = val;
389
}
390
#endif
391
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
392
/******************************************************************//**
1819.5.106 by stewart at flamingspork
[patch 106/129] Merge patch for revision 1915 from InnoDB SVN:
393
Closes insert buffer and frees the data structures. */
394
UNIV_INTERN
395
void
396
ibuf_close(void)
397
/*============*/
398
{
399
	mutex_free(&ibuf_pessimistic_insert_mutex);
400
	memset(&ibuf_pessimistic_insert_mutex,
401
	       0x0, sizeof(ibuf_pessimistic_insert_mutex));
402
403
	mutex_free(&ibuf_mutex);
404
	memset(&ibuf_mutex, 0x0, sizeof(ibuf_mutex));
405
406
	mutex_free(&ibuf_bitmap_mutex);
407
	memset(&ibuf_bitmap_mutex, 0x0, sizeof(ibuf_mutex));
408
409
	mem_free(ibuf);
410
	ibuf = NULL;
411
}
412
413
/******************************************************************//**
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
414
Updates the size information of the ibuf, assuming the segment size has not
415
changed. */
416
static
417
void
418
ibuf_size_update(
419
/*=============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
420
	const page_t*	root,	/*!< in: ibuf tree root */
421
	mtr_t*		mtr)	/*!< in: mtr */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
422
{
423
	ut_ad(mutex_own(&ibuf_mutex));
424
425
	ibuf->free_list_len = flst_get_len(root + PAGE_HEADER
426
					   + PAGE_BTR_IBUF_FREE_LIST, mtr);
427
428
	ibuf->height = 1 + btr_page_get_level(root, mtr);
429
430
	/* the '1 +' is the ibuf header page */
431
	ibuf->size = ibuf->seg_size - (1 + ibuf->free_list_len);
432
433
	ibuf->empty = page_get_n_recs(root) == 0;
434
}
435
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
436
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
437
Creates the insert buffer data structure at a database startup and initializes
438
the data structures for the insert buffer. */
439
UNIV_INTERN
440
void
441
ibuf_init_at_db_start(void)
442
/*=======================*/
443
{
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
444
	page_t*		root;
445
	mtr_t		mtr;
446
	dict_table_t*	table;
447
	mem_heap_t*	heap;
448
	dict_index_t*	index;
449
	ulint		n_used;
450
	page_t*		header_page;
451
	ulint		error;
452
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
453
	ibuf = mem_alloc(sizeof(ibuf_t));
454
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
455
	memset(ibuf, 0, sizeof(*ibuf));
456
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
457
	/* Note that also a pessimistic delete can sometimes make a B-tree
458
	grow in size, as the references on the upper levels of the tree can
459
	change */
460
461
	ibuf->max_size = buf_pool_get_curr_size() / UNIV_PAGE_SIZE
462
		/ IBUF_POOL_SIZE_PER_MAX_SIZE;
463
464
	mutex_create(&ibuf_pessimistic_insert_mutex,
465
		     SYNC_IBUF_PESS_INSERT_MUTEX);
466
467
	mutex_create(&ibuf_mutex, SYNC_IBUF_MUTEX);
468
469
	mutex_create(&ibuf_bitmap_mutex, SYNC_IBUF_BITMAP_MUTEX);
470
471
	mtr_start(&mtr);
472
473
	mutex_enter(&ibuf_mutex);
474
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
475
	mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, NULL), &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
476
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
477
	header_page = ibuf_header_page_get(&mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
478
479
	fseg_n_reserved_pages(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
480
			      &n_used, &mtr);
481
	ibuf_enter();
482
483
	ut_ad(n_used >= 2);
484
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
485
	ibuf->seg_size = n_used;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
486
487
	{
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
488
		buf_block_t*	block;
489
490
		block = buf_page_get(
491
			IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO,
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
492
			RW_X_LATCH, &mtr);
493
		buf_block_dbg_add_level(block, SYNC_TREE_NODE);
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
494
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
495
		root = buf_block_get_frame(block);
496
	}
497
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
498
	ibuf_size_update(root, &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
499
	mutex_exit(&ibuf_mutex);
500
501
	mtr_commit(&mtr);
502
503
	ibuf_exit();
504
505
	heap = mem_heap_create(450);
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
506
507
	/* Use old-style record format for the insert buffer. */
508
	table = dict_mem_table_create(IBUF_TABLE_NAME, IBUF_SPACE_ID, 1, 0);
509
510
	dict_mem_table_add_col(table, heap, "DUMMY_COLUMN", DATA_BINARY, 0, 0);
511
512
	table->id = ut_dulint_add(DICT_IBUF_ID_MIN, IBUF_SPACE_ID);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
513
514
	dict_table_add_to_cache(table, heap);
515
	mem_heap_free(heap);
516
517
	index = dict_mem_index_create(
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
518
		IBUF_TABLE_NAME, "CLUST_IND",
519
		IBUF_SPACE_ID, DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, 1);
520
521
	dict_mem_index_add_field(index, "DUMMY_COLUMN", 0);
522
523
	index->id = ut_dulint_add(DICT_IBUF_ID_MIN, IBUF_SPACE_ID);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
524
525
	error = dict_index_add_to_cache(table, index,
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
526
					FSP_IBUF_TREE_ROOT_PAGE_NO, FALSE);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
527
	ut_a(error == DB_SUCCESS);
528
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
529
	ibuf->index = dict_table_get_first_index(table);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
530
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
531
#endif /* !UNIV_HOTBACKUP */
532
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
533
Initializes an ibuf bitmap page. */
534
UNIV_INTERN
535
void
536
ibuf_bitmap_page_init(
537
/*==================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
538
	buf_block_t*	block,	/*!< in: bitmap page */
539
	mtr_t*		mtr)	/*!< in: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
540
{
541
	page_t*	page;
542
	ulint	byte_offset;
543
	ulint	zip_size = buf_block_get_zip_size(block);
544
545
	ut_a(ut_is_2pow(zip_size));
546
547
	page = buf_block_get_frame(block);
548
	fil_page_set_type(page, FIL_PAGE_IBUF_BITMAP);
549
550
	/* Write all zeros to the bitmap */
551
552
	if (!zip_size) {
553
		byte_offset = UT_BITS_IN_BYTES(UNIV_PAGE_SIZE
554
					       * IBUF_BITS_PER_PAGE);
555
	} else {
556
		byte_offset = UT_BITS_IN_BYTES(zip_size * IBUF_BITS_PER_PAGE);
557
	}
558
559
	memset(page + IBUF_BITMAP, 0, byte_offset);
560
561
	/* The remaining area (up to the page trailer) is uninitialized. */
562
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
563
#ifndef UNIV_HOTBACKUP
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
564
	mlog_write_initial_log_record(page, MLOG_IBUF_BITMAP_INIT, mtr);
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
565
#endif /* !UNIV_HOTBACKUP */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
566
}
567
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
568
/*********************************************************************//**
569
Parses a redo log record of an ibuf bitmap page init.
570
@return	end of log record or NULL */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
571
UNIV_INTERN
572
byte*
573
ibuf_parse_bitmap_init(
574
/*===================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
575
	byte*		ptr,	/*!< in: buffer */
576
	byte*		end_ptr __attribute__((unused)), /*!< in: buffer end */
577
	buf_block_t*	block,	/*!< in: block or NULL */
578
	mtr_t*		mtr)	/*!< in: mtr or NULL */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
579
{
580
	ut_ad(ptr && end_ptr);
581
582
	if (block) {
583
		ibuf_bitmap_page_init(block, mtr);
584
	}
585
586
	return(ptr);
587
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
588
#ifndef UNIV_HOTBACKUP
589
/********************************************************************//**
590
Gets the desired bits for a given page from a bitmap page.
591
@return	value of bits */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
592
UNIV_INLINE
593
ulint
594
ibuf_bitmap_page_get_bits(
595
/*======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
596
	const page_t*	page,	/*!< in: bitmap page */
597
	ulint		page_no,/*!< in: page whose bits to get */
598
	ulint		zip_size,/*!< in: compressed page size in bytes;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
599
				0 for uncompressed pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
600
	ulint		bit,	/*!< in: IBUF_BITMAP_FREE,
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
601
				IBUF_BITMAP_BUFFERED, ... */
602
	mtr_t*		mtr __attribute__((unused)))
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
603
				/*!< in: mtr containing an
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
604
				x-latch to the bitmap page */
605
{
606
	ulint	byte_offset;
607
	ulint	bit_offset;
608
	ulint	map_byte;
609
	ulint	value;
610
611
	ut_ad(bit < IBUF_BITS_PER_PAGE);
612
#if IBUF_BITS_PER_PAGE % 2
613
# error "IBUF_BITS_PER_PAGE % 2 != 0"
614
#endif
615
	ut_ad(ut_is_2pow(zip_size));
616
	ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
617
618
	if (!zip_size) {
619
		bit_offset = (page_no % UNIV_PAGE_SIZE) * IBUF_BITS_PER_PAGE
620
			+ bit;
621
	} else {
622
		bit_offset = (page_no & (zip_size - 1)) * IBUF_BITS_PER_PAGE
623
			+ bit;
624
	}
625
626
	byte_offset = bit_offset / 8;
627
	bit_offset = bit_offset % 8;
628
629
	ut_ad(byte_offset + IBUF_BITMAP < UNIV_PAGE_SIZE);
630
631
	map_byte = mach_read_from_1(page + IBUF_BITMAP + byte_offset);
632
633
	value = ut_bit_get_nth(map_byte, bit_offset);
634
635
	if (bit == IBUF_BITMAP_FREE) {
636
		ut_ad(bit_offset + 1 < 8);
637
638
		value = value * 2 + ut_bit_get_nth(map_byte, bit_offset + 1);
639
	}
640
641
	return(value);
642
}
643
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
644
/********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
645
Sets the desired bit for a given page in a bitmap page. */
646
static
647
void
648
ibuf_bitmap_page_set_bits(
649
/*======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
650
	page_t*	page,	/*!< in: bitmap page */
651
	ulint	page_no,/*!< in: page whose bits to set */
652
	ulint	zip_size,/*!< in: compressed page size in bytes;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
653
			0 for uncompressed pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
654
	ulint	bit,	/*!< in: IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ... */
655
	ulint	val,	/*!< in: value to set */
656
	mtr_t*	mtr)	/*!< in: mtr containing an x-latch to the bitmap page */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
657
{
658
	ulint	byte_offset;
659
	ulint	bit_offset;
660
	ulint	map_byte;
661
662
	ut_ad(bit < IBUF_BITS_PER_PAGE);
663
#if IBUF_BITS_PER_PAGE % 2
664
# error "IBUF_BITS_PER_PAGE % 2 != 0"
665
#endif
666
	ut_ad(ut_is_2pow(zip_size));
667
	ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
668
#ifdef UNIV_IBUF_COUNT_DEBUG
669
	ut_a((bit != IBUF_BITMAP_BUFFERED) || (val != FALSE)
670
	     || (0 == ibuf_count_get(page_get_space_id(page),
671
				     page_no)));
672
#endif
673
	if (!zip_size) {
674
		bit_offset = (page_no % UNIV_PAGE_SIZE) * IBUF_BITS_PER_PAGE
675
			+ bit;
676
	} else {
677
		bit_offset = (page_no & (zip_size - 1)) * IBUF_BITS_PER_PAGE
678
			+ bit;
679
	}
680
681
	byte_offset = bit_offset / 8;
682
	bit_offset = bit_offset % 8;
683
684
	ut_ad(byte_offset + IBUF_BITMAP < UNIV_PAGE_SIZE);
685
686
	map_byte = mach_read_from_1(page + IBUF_BITMAP + byte_offset);
687
688
	if (bit == IBUF_BITMAP_FREE) {
689
		ut_ad(bit_offset + 1 < 8);
690
		ut_ad(val <= 3);
691
692
		map_byte = ut_bit_set_nth(map_byte, bit_offset, val / 2);
693
		map_byte = ut_bit_set_nth(map_byte, bit_offset + 1, val % 2);
694
	} else {
695
		ut_ad(val <= 1);
696
		map_byte = ut_bit_set_nth(map_byte, bit_offset, val);
697
	}
698
699
	mlog_write_ulint(page + IBUF_BITMAP + byte_offset, map_byte,
700
			 MLOG_1BYTE, mtr);
701
}
702
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
703
/********************************************************************//**
704
Calculates the bitmap page number for a given page number.
705
@return	the bitmap page number where the file page is mapped */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
706
UNIV_INLINE
707
ulint
708
ibuf_bitmap_page_no_calc(
709
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
710
	ulint	zip_size,	/*!< in: compressed page size in bytes;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
711
				0 for uncompressed pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
712
	ulint	page_no)	/*!< in: tablespace page number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
713
{
714
	ut_ad(ut_is_2pow(zip_size));
715
716
	if (!zip_size) {
717
		return(FSP_IBUF_BITMAP_OFFSET
718
		       + (page_no & ~(UNIV_PAGE_SIZE - 1)));
719
	} else {
720
		return(FSP_IBUF_BITMAP_OFFSET
721
		       + (page_no & ~(zip_size - 1)));
722
	}
723
}
724
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
725
/********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
726
Gets the ibuf bitmap page where the bits describing a given file page are
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
727
stored.
728
@return bitmap page where the file page is mapped, that is, the bitmap
729
page containing the descriptor bits for the file page; the bitmap page
730
is x-latched */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
731
static
732
page_t*
733
ibuf_bitmap_get_map_page(
734
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
735
	ulint	space,	/*!< in: space id of the file page */
736
	ulint	page_no,/*!< in: page number of the file page */
737
	ulint	zip_size,/*!< in: compressed page size in bytes;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
738
			0 for uncompressed pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
739
	mtr_t*	mtr)	/*!< in: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
740
{
741
	buf_block_t*	block;
742
743
	block = buf_page_get(space, zip_size,
744
			     ibuf_bitmap_page_no_calc(zip_size, page_no),
745
			     RW_X_LATCH, mtr);
746
	buf_block_dbg_add_level(block, SYNC_IBUF_BITMAP);
747
748
	return(buf_block_get_frame(block));
749
}
750
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
751
/************************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
752
Sets the free bits of the page in the ibuf bitmap. This is done in a separate
753
mini-transaction, hence this operation does not restrict further work to only
754
ibuf bitmap operations, which would result if the latch to the bitmap page
755
were kept. */
756
UNIV_INLINE
757
void
758
ibuf_set_free_bits_low(
759
/*===================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
760
	ulint			zip_size,/*!< in: compressed page size in bytes;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
761
					0 for uncompressed pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
762
	const buf_block_t*	block,	/*!< in: index page; free bits are set if
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
763
					the index is non-clustered and page
764
					level is 0 */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
765
	ulint			val,	/*!< in: value to set: < 4 */
766
	mtr_t*			mtr)	/*!< in/out: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
767
{
768
	page_t*	bitmap_page;
769
	ulint	space;
770
	ulint	page_no;
771
772
	if (!page_is_leaf(buf_block_get_frame(block))) {
773
774
		return;
775
	}
776
777
	space = buf_block_get_space(block);
778
	page_no = buf_block_get_page_no(block);
779
	bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
780
#ifdef UNIV_IBUF_DEBUG
781
# if 0
782
	fprintf(stderr,
783
		"Setting space %lu page %lu free bits to %lu should be %lu\n",
784
		space, page_no, val,
785
		ibuf_index_page_calc_free(zip_size, block));
786
# endif
787
788
	ut_a(val <= ibuf_index_page_calc_free(zip_size, block));
789
#endif /* UNIV_IBUF_DEBUG */
790
	ibuf_bitmap_page_set_bits(bitmap_page, page_no, zip_size,
791
				  IBUF_BITMAP_FREE, val, mtr);
792
}
793
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
794
/************************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
795
Sets the free bit of the page in the ibuf bitmap. This is done in a separate
796
mini-transaction, hence this operation does not restrict further work to only
797
ibuf bitmap operations, which would result if the latch to the bitmap page
798
were kept. */
799
UNIV_INTERN
800
void
801
ibuf_set_free_bits_func(
802
/*====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
803
	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.
804
				free bit is reset if page level is 0 */
805
#ifdef UNIV_IBUF_DEBUG
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
806
	ulint		max_val,/*!< in: ULINT_UNDEFINED or a maximum
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
807
				value which the bits must have before
808
				setting; this is for debugging */
809
#endif /* UNIV_IBUF_DEBUG */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
810
	ulint		val)	/*!< in: value to set: < 4 */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
811
{
812
	mtr_t	mtr;
813
	page_t*	page;
814
	page_t*	bitmap_page;
815
	ulint	space;
816
	ulint	page_no;
817
	ulint	zip_size;
818
819
	page = buf_block_get_frame(block);
820
821
	if (!page_is_leaf(page)) {
822
823
		return;
824
	}
825
826
	mtr_start(&mtr);
827
828
	space = buf_block_get_space(block);
829
	page_no = buf_block_get_page_no(block);
830
	zip_size = buf_block_get_zip_size(block);
831
	bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, &mtr);
832
833
#ifdef UNIV_IBUF_DEBUG
834
	if (max_val != ULINT_UNDEFINED) {
835
		ulint	old_val;
836
837
		old_val = ibuf_bitmap_page_get_bits(
838
			bitmap_page, page_no, zip_size,
839
			IBUF_BITMAP_FREE, &mtr);
840
# if 0
841
		if (old_val != max_val) {
842
			fprintf(stderr,
843
				"Ibuf: page %lu old val %lu max val %lu\n",
844
				page_get_page_no(page),
845
				old_val, max_val);
846
		}
847
# endif
848
849
		ut_a(old_val <= max_val);
850
	}
851
# if 0
852
	fprintf(stderr, "Setting page no %lu free bits to %lu should be %lu\n",
853
		page_get_page_no(page), val,
854
		ibuf_index_page_calc_free(zip_size, block));
855
# endif
856
857
	ut_a(val <= ibuf_index_page_calc_free(zip_size, block));
858
#endif /* UNIV_IBUF_DEBUG */
859
	ibuf_bitmap_page_set_bits(bitmap_page, page_no, zip_size,
860
				  IBUF_BITMAP_FREE, val, &mtr);
861
	mtr_commit(&mtr);
862
}
863
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
864
/************************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
865
Resets the free bits of the page in the ibuf bitmap. This is done in a
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
866
separate mini-transaction, hence this operation does not restrict
867
further work to only ibuf bitmap operations, which would result if the
868
latch to the bitmap page were kept.  NOTE: The free bits in the insert
869
buffer bitmap must never exceed the free space on a page.  It is safe
870
to decrement or reset the bits in the bitmap in a mini-transaction
871
that is committed before the mini-transaction that affects the free
872
space. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
873
UNIV_INTERN
874
void
875
ibuf_reset_free_bits(
876
/*=================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
877
	buf_block_t*	block)	/*!< in: index page; free bits are set to 0
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
878
				if the index is a non-clustered
879
				non-unique, and page level is 0 */
880
{
881
	ibuf_set_free_bits(block, 0, ULINT_UNDEFINED);
882
}
883
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
884
/**********************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
885
Updates the free bits for an uncompressed page to reflect the present
886
state.  Does this in the mtr given, which means that the latching
887
order rules virtually prevent any further operations for this OS
888
thread until mtr is committed.  NOTE: The free bits in the insert
889
buffer bitmap must never exceed the free space on a page.  It is safe
890
to set the free bits in the same mini-transaction that updated the
891
page. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
892
UNIV_INTERN
893
void
894
ibuf_update_free_bits_low(
895
/*======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
896
	const buf_block_t*	block,		/*!< in: index page */
897
	ulint			max_ins_size,	/*!< in: value of
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
898
						maximum insert size
899
						with reorganize before
900
						the latest operation
901
						performed to the page */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
902
	mtr_t*			mtr)		/*!< in/out: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
903
{
904
	ulint	before;
905
	ulint	after;
906
907
	ut_a(!buf_block_get_page_zip(block));
908
909
	before = ibuf_index_page_calc_free_bits(0, max_ins_size);
910
911
	after = ibuf_index_page_calc_free(0, block);
912
913
	/* This approach cannot be used on compressed pages, since the
914
	computed value of "before" often does not match the current
915
	state of the bitmap.  This is because the free space may
916
	increase or decrease when a compressed page is reorganized. */
917
	if (before != after) {
918
		ibuf_set_free_bits_low(0, block, after, mtr);
919
	}
920
}
921
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
922
/**********************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
923
Updates the free bits for a compressed page to reflect the present
924
state.  Does this in the mtr given, which means that the latching
925
order rules virtually prevent any further operations for this OS
926
thread until mtr is committed.  NOTE: The free bits in the insert
927
buffer bitmap must never exceed the free space on a page.  It is safe
928
to set the free bits in the same mini-transaction that updated the
929
page. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
930
UNIV_INTERN
931
void
932
ibuf_update_free_bits_zip(
933
/*======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
934
	buf_block_t*	block,	/*!< in/out: index page */
935
	mtr_t*		mtr)	/*!< in/out: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
936
{
937
	page_t*	bitmap_page;
938
	ulint	space;
939
	ulint	page_no;
940
	ulint	zip_size;
941
	ulint	after;
942
943
	space = buf_block_get_space(block);
944
	page_no = buf_block_get_page_no(block);
945
	zip_size = buf_block_get_zip_size(block);
946
947
	ut_a(page_is_leaf(buf_block_get_frame(block)));
948
	ut_a(zip_size);
949
950
	bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
951
952
	after = ibuf_index_page_calc_free_zip(zip_size, block);
953
954
	if (after == 0) {
955
		/* We move the page to the front of the buffer pool LRU list:
956
		the purpose of this is to prevent those pages to which we
957
		cannot make inserts using the insert buffer from slipping
958
		out of the buffer pool */
959
960
		buf_page_make_young(&block->page);
961
	}
962
963
	ibuf_bitmap_page_set_bits(bitmap_page, page_no, zip_size,
964
				  IBUF_BITMAP_FREE, after, mtr);
965
}
966
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
967
/**********************************************************************//**
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
968
Updates the free bits for the two pages to reflect the present state.
969
Does this in the mtr given, which means that the latching order rules
970
virtually prevent any further operations until mtr is committed.
971
NOTE: The free bits in the insert buffer bitmap must never exceed the
972
free space on a page.  It is safe to set the free bits in the same
973
mini-transaction that updated the pages. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
974
UNIV_INTERN
975
void
976
ibuf_update_free_bits_for_two_pages_low(
977
/*====================================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
978
	ulint		zip_size,/*!< in: compressed page size in bytes;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
979
				0 for uncompressed pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
980
	buf_block_t*	block1,	/*!< in: index page */
981
	buf_block_t*	block2,	/*!< in: index page */
982
	mtr_t*		mtr)	/*!< in: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
983
{
984
	ulint	state;
985
986
	/* As we have to x-latch two random bitmap pages, we have to acquire
987
	the bitmap mutex to prevent a deadlock with a similar operation
988
	performed by another OS thread. */
989
990
	mutex_enter(&ibuf_bitmap_mutex);
991
992
	state = ibuf_index_page_calc_free(zip_size, block1);
993
994
	ibuf_set_free_bits_low(zip_size, block1, state, mtr);
995
996
	state = ibuf_index_page_calc_free(zip_size, block2);
997
998
	ibuf_set_free_bits_low(zip_size, block2, state, mtr);
999
1000
	mutex_exit(&ibuf_bitmap_mutex);
1001
}
1002
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1003
/**********************************************************************//**
1004
Returns TRUE if the page is one of the fixed address ibuf pages.
1005
@return	TRUE if a fixed address ibuf i/o page */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1006
UNIV_INLINE
1007
ibool
1008
ibuf_fixed_addr_page(
1009
/*=================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1010
	ulint	space,	/*!< in: space id */
1011
	ulint	zip_size,/*!< in: compressed page size in bytes;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1012
			0 for uncompressed pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1013
	ulint	page_no)/*!< in: page number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1014
{
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1015
	return((space == IBUF_SPACE_ID && page_no == IBUF_TREE_ROOT_PAGE_NO)
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1016
	       || ibuf_bitmap_page(zip_size, page_no));
1017
}
1018
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1019
/***********************************************************************//**
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1020
Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1021
Must not be called when recv_no_ibuf_operations==TRUE.
1022
@return	TRUE if level 2 or level 3 page */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1023
UNIV_INTERN
1024
ibool
1025
ibuf_page(
1026
/*======*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1027
	ulint	space,	/*!< in: space id */
1028
	ulint	zip_size,/*!< in: compressed page size in bytes, or 0 */
1029
	ulint	page_no,/*!< in: page number */
1030
	mtr_t*	mtr)	/*!< in: mtr which will contain an x-latch to the
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1031
			bitmap page if the page is not one of the fixed
1032
			address ibuf pages, or NULL, in which case a new
1033
			transaction is created. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1034
{
1035
	ibool	ret;
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1036
	mtr_t	local_mtr;
1037
	page_t*	bitmap_page;
1038
1039
	ut_ad(!recv_no_ibuf_operations);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1040
1041
	if (ibuf_fixed_addr_page(space, zip_size, page_no)) {
1042
1043
		return(TRUE);
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1044
	} else if (space != IBUF_SPACE_ID) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1045
1046
		return(FALSE);
1047
	}
1048
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1049
	ut_ad(fil_space_get_type(IBUF_SPACE_ID) == FIL_TABLESPACE);
1050
1051
	if (mtr == NULL) {
1052
		mtr = &local_mtr;
1053
		mtr_start(mtr);
1054
	}
1055
1056
	bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1057
1058
	ret = ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size,
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1059
					IBUF_BITMAP_IBUF, mtr);
1060
1061
	if (mtr == &local_mtr) {
1062
		mtr_commit(mtr);
1063
	}
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1064
1065
	return(ret);
1066
}
1067
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1068
/********************************************************************//**
1069
Returns the page number field of an ibuf record.
1070
@return	page number */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1071
static
1072
ulint
1073
ibuf_rec_get_page_no(
1074
/*=================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1075
	const rec_t*	rec)	/*!< in: ibuf record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1076
{
1077
	const byte*	field;
1078
	ulint		len;
1079
1080
	ut_ad(ibuf_inside());
1081
	ut_ad(rec_get_n_fields_old(rec) > 2);
1082
1083
	field = rec_get_nth_field_old(rec, 1, &len);
1084
1085
	if (len == 1) {
1086
		/* This is of the >= 4.1.x record format */
1087
		ut_a(trx_sys_multiple_tablespace_format);
1088
1089
		field = rec_get_nth_field_old(rec, 2, &len);
1090
	} else {
1091
		ut_a(trx_doublewrite_must_reset_space_ids);
1092
		ut_a(!trx_sys_multiple_tablespace_format);
1093
1094
		field = rec_get_nth_field_old(rec, 0, &len);
1095
	}
1096
1097
	ut_a(len == 4);
1098
1099
	return(mach_read_from_4(field));
1100
}
1101
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1102
/********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1103
Returns the space id field of an ibuf record. For < 4.1.x format records
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1104
returns 0.
1105
@return	space id */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1106
static
1107
ulint
1108
ibuf_rec_get_space(
1109
/*===============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1110
	const rec_t*	rec)	/*!< in: ibuf record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1111
{
1112
	const byte*	field;
1113
	ulint		len;
1114
1115
	ut_ad(ibuf_inside());
1116
	ut_ad(rec_get_n_fields_old(rec) > 2);
1117
1118
	field = rec_get_nth_field_old(rec, 1, &len);
1119
1120
	if (len == 1) {
1121
		/* This is of the >= 4.1.x record format */
1122
1123
		ut_a(trx_sys_multiple_tablespace_format);
1124
		field = rec_get_nth_field_old(rec, 0, &len);
1125
		ut_a(len == 4);
1126
1127
		return(mach_read_from_4(field));
1128
	}
1129
1130
	ut_a(trx_doublewrite_must_reset_space_ids);
1131
	ut_a(!trx_sys_multiple_tablespace_format);
1132
1133
	return(0);
1134
}
1135
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1136
/********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1137
Creates a dummy index for inserting a record to a non-clustered index.
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1138
1139
@return	dummy index */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1140
static
1141
dict_index_t*
1142
ibuf_dummy_index_create(
1143
/*====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1144
	ulint		n,	/*!< in: number of fields */
1145
	ibool		comp)	/*!< in: TRUE=use compact record format */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1146
{
1147
	dict_table_t*	table;
1148
	dict_index_t*	index;
1149
1150
	table = dict_mem_table_create("IBUF_DUMMY",
1151
				      DICT_HDR_SPACE, n,
1152
				      comp ? DICT_TF_COMPACT : 0);
1153
1154
	index = dict_mem_index_create("IBUF_DUMMY", "IBUF_DUMMY",
1155
				      DICT_HDR_SPACE, 0, n);
1156
1157
	index->table = table;
1158
1159
	/* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
1160
	index->cached = TRUE;
1161
1162
	return(index);
1163
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1164
/********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1165
Add a column to the dummy index */
1166
static
1167
void
1168
ibuf_dummy_index_add_col(
1169
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1170
	dict_index_t*	index,	/*!< in: dummy index */
1171
	const dtype_t*	type,	/*!< in: the data type of the column */
1172
	ulint		len)	/*!< in: length of the column */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1173
{
1174
	ulint	i	= index->table->n_def;
1175
	dict_mem_table_add_col(index->table, NULL, NULL,
1176
			       dtype_get_mtype(type),
1177
			       dtype_get_prtype(type),
1178
			       dtype_get_len(type));
1179
	dict_index_add_col(index, index->table,
1180
			   dict_table_get_nth_col(index->table, i), len);
1181
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1182
/********************************************************************//**
1183
Deallocates a dummy index for inserting a record to a non-clustered index. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1184
static
1185
void
1186
ibuf_dummy_index_free(
1187
/*==================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1188
	dict_index_t*	index)	/*!< in, own: dummy index */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1189
{
1190
	dict_table_t*	table = index->table;
1191
1192
	dict_mem_index_free(index);
1193
	dict_mem_table_free(table);
1194
}
1195
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1196
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1197
Builds the entry to insert into a non-clustered index when we have the
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1198
corresponding record in an ibuf index.
1199
1200
NOTE that as we copy pointers to fields in ibuf_rec, the caller must
1201
hold a latch to the ibuf_rec page as long as the entry is used!
1202
1203
@return own: entry to insert to a non-clustered index */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1204
UNIV_INLINE
1205
dtuple_t*
1206
ibuf_build_entry_pre_4_1_x(
1207
/*=======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1208
	const rec_t*	ibuf_rec,	/*!< in: record in an insert buffer */
1209
	mem_heap_t*	heap,		/*!< in: heap where built */
1210
	dict_index_t**	pindex)		/*!< out, own: dummy index that
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1211
					describes the entry */
1212
{
1213
	ulint		i;
1214
	ulint		len;
1215
	const byte*	types;
1216
	dtuple_t*	tuple;
1217
	ulint		n_fields;
1218
1219
	ut_a(trx_doublewrite_must_reset_space_ids);
1220
	ut_a(!trx_sys_multiple_tablespace_format);
1221
1222
	n_fields = rec_get_n_fields_old(ibuf_rec) - 2;
1223
	tuple = dtuple_create(heap, n_fields);
1224
	types = rec_get_nth_field_old(ibuf_rec, 1, &len);
1225
1226
	ut_a(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
1227
1228
	for (i = 0; i < n_fields; i++) {
1229
		const byte*	data;
1230
		dfield_t*	field;
1231
1232
		field = dtuple_get_nth_field(tuple, i);
1233
1234
		data = rec_get_nth_field_old(ibuf_rec, i + 2, &len);
1235
1236
		dfield_set_data(field, data, len);
1237
1238
		dtype_read_for_order_and_null_size(
1239
			dfield_get_type(field),
1240
			types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
1241
	}
1242
1243
	*pindex = ibuf_dummy_index_create(n_fields, FALSE);
1244
1245
	return(tuple);
1246
}
1247
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1248
/*********************************************************************//**
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1249
Builds the entry to insert into a non-clustered index when we have the
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1250
corresponding record in an ibuf index.
1251
1252
NOTE that as we copy pointers to fields in ibuf_rec, the caller must
1253
hold a latch to the ibuf_rec page as long as the entry is used!
1254
1255
@return own: entry to insert to a non-clustered index */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1256
static
1257
dtuple_t*
1258
ibuf_build_entry_from_ibuf_rec(
1259
/*===========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1260
	const rec_t*	ibuf_rec,	/*!< in: record in an insert buffer */
1261
	mem_heap_t*	heap,		/*!< in: heap where built */
1262
	dict_index_t**	pindex)		/*!< out, own: dummy index that
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1263
					describes the entry */
1264
{
1265
	dtuple_t*	tuple;
1266
	dfield_t*	field;
1267
	ulint		n_fields;
1268
	const byte*	types;
1269
	const byte*	data;
1270
	ulint		len;
1271
	ulint		i;
1272
	dict_index_t*	index;
1273
1274
	data = rec_get_nth_field_old(ibuf_rec, 1, &len);
1275
1276
	if (len > 1) {
1277
		/* This a < 4.1.x format record */
1278
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1279
		return(ibuf_build_entry_pre_4_1_x(ibuf_rec, heap, pindex));
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1280
	}
1281
1282
	/* This a >= 4.1.x format record */
1283
1284
	ut_a(trx_sys_multiple_tablespace_format);
1285
	ut_a(*data == 0);
1286
	ut_a(rec_get_n_fields_old(ibuf_rec) > 4);
1287
1288
	n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
1289
1290
	tuple = dtuple_create(heap, n_fields);
1291
1292
	types = rec_get_nth_field_old(ibuf_rec, 3, &len);
1293
1294
	ut_a(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE <= 1);
1295
	index = ibuf_dummy_index_create(
1296
		n_fields, len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
1297
1298
	if (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) {
1299
		/* compact record format */
1300
		len--;
1301
		ut_a(*types == 0);
1302
		types++;
1303
	}
1304
1305
	ut_a(len == n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
1306
1307
	for (i = 0; i < n_fields; i++) {
1308
		field = dtuple_get_nth_field(tuple, i);
1309
1310
		data = rec_get_nth_field_old(ibuf_rec, i + 4, &len);
1311
1312
		dfield_set_data(field, data, len);
1313
1314
		dtype_new_read_for_order_and_null_size(
1315
			dfield_get_type(field),
1316
			types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
1317
1318
		ibuf_dummy_index_add_col(index, dfield_get_type(field), len);
1319
	}
1320
1321
	/* Prevent an ut_ad() failure in page_zip_write_rec() by
1322
	adding system columns to the dummy table pointed to by the
1323
	dummy secondary index.  The insert buffer is only used for
1324
	secondary indexes, whose records never contain any system
1325
	columns, such as DB_TRX_ID. */
1326
	ut_d(dict_table_add_system_columns(index->table, index->table->heap));
1327
1328
	*pindex = index;
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1329
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1330
	return(tuple);
1331
}
1332
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1333
/********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1334
Returns the space taken by a stored non-clustered index entry if converted to
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1335
an index record.
1336
@return size of index record in bytes + an upper limit of the space
1337
taken in the page directory */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1338
static
1339
ulint
1340
ibuf_rec_get_volume(
1341
/*================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1342
	const rec_t*	ibuf_rec)/*!< in: ibuf record */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1343
{
1344
	dtype_t		dtype;
1345
	ibool		new_format	= FALSE;
1346
	ulint		data_size	= 0;
1347
	ulint		n_fields;
1348
	const byte*	types;
1349
	const byte*	data;
1350
	ulint		len;
1351
	ulint		i;
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1352
	ulint		comp;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1353
1354
	ut_ad(ibuf_inside());
1355
	ut_ad(rec_get_n_fields_old(ibuf_rec) > 2);
1356
1357
	data = rec_get_nth_field_old(ibuf_rec, 1, &len);
1358
1359
	if (len > 1) {
1360
		/* < 4.1.x format record */
1361
1362
		ut_a(trx_doublewrite_must_reset_space_ids);
1363
		ut_a(!trx_sys_multiple_tablespace_format);
1364
1365
		n_fields = rec_get_n_fields_old(ibuf_rec) - 2;
1366
1367
		types = rec_get_nth_field_old(ibuf_rec, 1, &len);
1368
1369
		ut_ad(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1370
		comp = 0;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1371
	} else {
1372
		/* >= 4.1.x format record */
1373
1374
		ut_a(trx_sys_multiple_tablespace_format);
1375
		ut_a(*data == 0);
1376
1377
		types = rec_get_nth_field_old(ibuf_rec, 3, &len);
1378
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1379
		comp = len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE;
1380
1381
		ut_a(comp <= 1);
1382
		if (comp) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1383
			/* compact record format */
1384
			ulint		volume;
1385
			dict_index_t*	dummy_index;
1386
			mem_heap_t*	heap = mem_heap_create(500);
1387
			dtuple_t*	entry = ibuf_build_entry_from_ibuf_rec(
1388
				ibuf_rec, heap, &dummy_index);
1389
			volume = rec_get_converted_size(dummy_index, entry, 0);
1390
			ibuf_dummy_index_free(dummy_index);
1391
			mem_heap_free(heap);
1392
			return(volume + page_dir_calc_reserved_space(1));
1393
		}
1394
1395
		n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
1396
1397
		new_format = TRUE;
1398
	}
1399
1400
	for (i = 0; i < n_fields; i++) {
1401
		if (new_format) {
1402
			data = rec_get_nth_field_old(ibuf_rec, i + 4, &len);
1403
1404
			dtype_new_read_for_order_and_null_size(
1405
				&dtype, types + i
1406
				* DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
1407
		} else {
1408
			data = rec_get_nth_field_old(ibuf_rec, i + 2, &len);
1409
1410
			dtype_read_for_order_and_null_size(
1411
				&dtype, types + i
1412
				* DATA_ORDER_NULL_TYPE_BUF_SIZE);
1413
		}
1414
1415
		if (len == UNIV_SQL_NULL) {
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1416
			data_size += dtype_get_sql_null_size(&dtype, comp);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1417
		} else {
1418
			data_size += len;
1419
		}
1420
	}
1421
1422
	return(data_size + rec_get_converted_extra_size(data_size, n_fields, 0)
1423
	       + page_dir_calc_reserved_space(1));
1424
}
1425
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1426
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1427
Builds the tuple to insert to an ibuf tree when we have an entry for a
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1428
non-clustered index.
1429
1430
NOTE that the original entry must be kept because we copy pointers to
1431
its fields.
1432
1433
@return	own: entry to insert into an ibuf index tree */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1434
static
1435
dtuple_t*
1436
ibuf_entry_build(
1437
/*=============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1438
	dict_index_t*	index,	/*!< in: non-clustered index */
1439
	const dtuple_t*	entry,	/*!< in: entry for a non-clustered index */
1440
	ulint		space,	/*!< in: space id */
1441
	ulint		page_no,/*!< in: index page number where entry should
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1442
				be inserted */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1443
	mem_heap_t*	heap)	/*!< in: heap into which to build */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1444
{
1445
	dtuple_t*	tuple;
1446
	dfield_t*	field;
1447
	const dfield_t*	entry_field;
1448
	ulint		n_fields;
1449
	byte*		buf;
1450
	byte*		buf2;
1451
	ulint		i;
1452
1453
	/* Starting from 4.1.x, we have to build a tuple whose
1454
	(1) first field is the space id,
1455
	(2) the second field a single marker byte (0) to tell that this
1456
	is a new format record,
1457
	(3) the third contains the page number, and
1458
	(4) the fourth contains the relevent type information of each data
1459
	field; the length of this field % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE is
1460
	(a) 0 for b-trees in the old format, and
1461
	(b) 1 for b-trees in the compact format, the first byte of the field
1462
	being the marker (0);
1463
	(5) and the rest of the fields are copied from entry. All fields
1464
	in the tuple are ordered like the type binary in our insert buffer
1465
	tree. */
1466
1467
	n_fields = dtuple_get_n_fields(entry);
1468
1469
	tuple = dtuple_create(heap, n_fields + 4);
1470
1471
	/* Store the space id in tuple */
1472
1473
	field = dtuple_get_nth_field(tuple, 0);
1474
1475
	buf = mem_heap_alloc(heap, 4);
1476
1477
	mach_write_to_4(buf, space);
1478
1479
	dfield_set_data(field, buf, 4);
1480
1481
	/* Store the marker byte field in tuple */
1482
1483
	field = dtuple_get_nth_field(tuple, 1);
1484
1485
	buf = mem_heap_alloc(heap, 1);
1486
1487
	/* We set the marker byte zero */
1488
1489
	mach_write_to_1(buf, 0);
1490
1491
	dfield_set_data(field, buf, 1);
1492
1493
	/* Store the page number in tuple */
1494
1495
	field = dtuple_get_nth_field(tuple, 2);
1496
1497
	buf = mem_heap_alloc(heap, 4);
1498
1499
	mach_write_to_4(buf, page_no);
1500
1501
	dfield_set_data(field, buf, 4);
1502
1503
	/* Store the type info in buf2, and add the fields from entry to
1504
	tuple */
1505
	buf2 = mem_heap_alloc(heap, n_fields
1506
			      * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
1507
			      + dict_table_is_comp(index->table));
1508
	if (dict_table_is_comp(index->table)) {
1509
		*buf2++ = 0; /* write the compact format indicator */
1510
	}
1511
	for (i = 0; i < n_fields; i++) {
1512
		ulint			fixed_len;
1513
		const dict_field_t*	ifield;
1514
1515
		/* We add 4 below because we have the 4 extra fields at the
1516
		start of an ibuf record */
1517
1518
		field = dtuple_get_nth_field(tuple, i + 4);
1519
		entry_field = dtuple_get_nth_field(entry, i);
1520
		dfield_copy(field, entry_field);
1521
1522
		ifield = dict_index_get_nth_field(index, i);
1523
		/* Prefix index columns of fixed-length columns are of
1524
		fixed length.  However, in the function call below,
1525
		dfield_get_type(entry_field) contains the fixed length
1526
		of the column in the clustered index.  Replace it with
1527
		the fixed length of the secondary index column. */
1528
		fixed_len = ifield->fixed_len;
1529
1530
#ifdef UNIV_DEBUG
1531
		if (fixed_len) {
1532
			/* dict_index_add_col() should guarantee these */
1533
			ut_ad(fixed_len <= (ulint)
1534
			      dfield_get_type(entry_field)->len);
1535
			if (ifield->prefix_len) {
1536
				ut_ad(ifield->prefix_len == fixed_len);
1537
			} else {
1538
				ut_ad(fixed_len == (ulint)
1539
				      dfield_get_type(entry_field)->len);
1540
			}
1541
		}
1542
#endif /* UNIV_DEBUG */
1543
1544
		dtype_new_store_for_order_and_null_size(
1545
			buf2 + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE,
1546
			dfield_get_type(entry_field), fixed_len);
1547
	}
1548
1549
	/* Store the type info in buf2 to field 3 of tuple */
1550
1551
	field = dtuple_get_nth_field(tuple, 3);
1552
1553
	if (dict_table_is_comp(index->table)) {
1554
		buf2--;
1555
	}
1556
1557
	dfield_set_data(field, buf2, n_fields
1558
			* DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
1559
			+ dict_table_is_comp(index->table));
1560
	/* Set all the types in the new tuple binary */
1561
1562
	dtuple_set_types_binary(tuple, n_fields + 4);
1563
1564
	return(tuple);
1565
}
1566
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1567
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1568
Builds a search tuple used to search buffered inserts for an index page.
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1569
This is for < 4.1.x format records
1570
@return	own: search tuple */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1571
static
1572
dtuple_t*
1573
ibuf_search_tuple_build(
1574
/*====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1575
	ulint		space,	/*!< in: space id */
1576
	ulint		page_no,/*!< in: index page number */
1577
	mem_heap_t*	heap)	/*!< in: heap into which to build */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1578
{
1579
	dtuple_t*	tuple;
1580
	dfield_t*	field;
1581
	byte*		buf;
1582
1583
	ut_a(space == 0);
1584
	ut_a(trx_doublewrite_must_reset_space_ids);
1585
	ut_a(!trx_sys_multiple_tablespace_format);
1586
1587
	tuple = dtuple_create(heap, 1);
1588
1589
	/* Store the page number in tuple */
1590
1591
	field = dtuple_get_nth_field(tuple, 0);
1592
1593
	buf = mem_heap_alloc(heap, 4);
1594
1595
	mach_write_to_4(buf, page_no);
1596
1597
	dfield_set_data(field, buf, 4);
1598
1599
	dtuple_set_types_binary(tuple, 1);
1600
1601
	return(tuple);
1602
}
1603
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1604
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1605
Builds a search tuple used to search buffered inserts for an index page.
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1606
This is for >= 4.1.x format records.
1607
@return	own: search tuple */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1608
static
1609
dtuple_t*
1610
ibuf_new_search_tuple_build(
1611
/*========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1612
	ulint		space,	/*!< in: space id */
1613
	ulint		page_no,/*!< in: index page number */
1614
	mem_heap_t*	heap)	/*!< in: heap into which to build */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1615
{
1616
	dtuple_t*	tuple;
1617
	dfield_t*	field;
1618
	byte*		buf;
1619
1620
	ut_a(trx_sys_multiple_tablespace_format);
1621
1622
	tuple = dtuple_create(heap, 3);
1623
1624
	/* Store the space id in tuple */
1625
1626
	field = dtuple_get_nth_field(tuple, 0);
1627
1628
	buf = mem_heap_alloc(heap, 4);
1629
1630
	mach_write_to_4(buf, space);
1631
1632
	dfield_set_data(field, buf, 4);
1633
1634
	/* Store the new format record marker byte */
1635
1636
	field = dtuple_get_nth_field(tuple, 1);
1637
1638
	buf = mem_heap_alloc(heap, 1);
1639
1640
	mach_write_to_1(buf, 0);
1641
1642
	dfield_set_data(field, buf, 1);
1643
1644
	/* Store the page number in tuple */
1645
1646
	field = dtuple_get_nth_field(tuple, 2);
1647
1648
	buf = mem_heap_alloc(heap, 4);
1649
1650
	mach_write_to_4(buf, page_no);
1651
1652
	dfield_set_data(field, buf, 4);
1653
1654
	dtuple_set_types_binary(tuple, 3);
1655
1656
	return(tuple);
1657
}
1658
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1659
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1660
Checks if there are enough pages in the free list of the ibuf tree that we
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1661
dare to start a pessimistic insert to the insert buffer.
1662
@return	TRUE if enough free pages in list */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1663
UNIV_INLINE
1664
ibool
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1665
ibuf_data_enough_free_for_insert(void)
1666
/*==================================*/
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1667
{
1668
	ut_ad(mutex_own(&ibuf_mutex));
1669
1670
	/* We want a big margin of free pages, because a B-tree can sometimes
1671
	grow in size also if records are deleted from it, as the node pointers
1672
	can change, and we must make sure that we are able to delete the
1673
	inserts buffered for pages that we read to the buffer pool, without
1674
	any risk of running out of free space in the insert buffer. */
1675
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1676
	return(ibuf->free_list_len >= (ibuf->size / 2) + 3 * ibuf->height);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1677
}
1678
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1679
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1680
Checks if there are enough pages in the free list of the ibuf tree that we
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1681
should remove them and free to the file space management.
1682
@return	TRUE if enough free pages in list */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1683
UNIV_INLINE
1684
ibool
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1685
ibuf_data_too_much_free(void)
1686
/*=========================*/
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1687
{
1688
	ut_ad(mutex_own(&ibuf_mutex));
1689
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1690
	return(ibuf->free_list_len >= 3 + (ibuf->size / 2) + 3 * ibuf->height);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1691
}
1692
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1693
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1694
Allocates a new page from the ibuf file segment and adds it to the free
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1695
list.
1696
@return	DB_SUCCESS, or DB_STRONG_FAIL if no space left */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1697
static
1698
ulint
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1699
ibuf_add_free_page(void)
1700
/*====================*/
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1701
{
1702
	mtr_t	mtr;
1703
	page_t*	header_page;
1704
	ulint	flags;
1705
	ulint	zip_size;
1706
	ulint	page_no;
1707
	page_t*	page;
1708
	page_t*	root;
1709
	page_t*	bitmap_page;
1710
1711
	mtr_start(&mtr);
1712
1713
	/* Acquire the fsp latch before the ibuf header, obeying the latching
1714
	order */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1715
	mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1716
	zip_size = dict_table_flags_to_zip_size(flags);
1717
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1718
	header_page = ibuf_header_page_get(&mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1719
1720
	/* Allocate a new page: NOTE that if the page has been a part of a
1721
	non-clustered index which has subsequently been dropped, then the
1722
	page may have buffered inserts in the insert buffer, and these
1723
	should be deleted from there. These get deleted when the page
1724
	allocation creates the page in buffer. Thus the call below may end
1725
	up calling the insert buffer routines and, as we yet have no latches
1726
	to insert buffer tree pages, these routines can run without a risk
1727
	of a deadlock. This is the reason why we created a special ibuf
1728
	header page apart from the ibuf tree. */
1729
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1730
	page_no = fseg_alloc_free_page(
1731
		header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP,
1732
		&mtr);
1733
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1734
	if (page_no == FIL_NULL) {
1735
		mtr_commit(&mtr);
1736
1737
		return(DB_STRONG_FAIL);
1738
	}
1739
1740
	{
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1741
		buf_block_t*	block;
1742
1743
		block = buf_page_get(
1744
			IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
1745
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1746
		buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1747
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1748
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1749
		page = buf_block_get_frame(block);
1750
	}
1751
1752
	ibuf_enter();
1753
1754
	mutex_enter(&ibuf_mutex);
1755
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1756
	root = ibuf_tree_root_get(&mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1757
1758
	/* Add the page to the free list and update the ibuf size data */
1759
1760
	flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
1761
		      page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
1762
1763
	mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_IBUF_FREE_LIST,
1764
			 MLOG_2BYTES, &mtr);
1765
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1766
	ibuf->seg_size++;
1767
	ibuf->free_list_len++;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1768
1769
	/* Set the bit indicating that this page is now an ibuf tree page
1770
	(level 2 page) */
1771
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1772
	bitmap_page = ibuf_bitmap_get_map_page(
1773
		IBUF_SPACE_ID, page_no, zip_size, &mtr);
1774
1775
	ibuf_bitmap_page_set_bits(
1776
		bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr);
1777
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1778
	mtr_commit(&mtr);
1779
1780
	mutex_exit(&ibuf_mutex);
1781
1782
	ibuf_exit();
1783
1784
	return(DB_SUCCESS);
1785
}
1786
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1787
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1788
Removes a page from the free list and frees it to the fsp system. */
1789
static
1790
void
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1791
ibuf_remove_free_page(void)
1792
/*=======================*/
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1793
{
1794
	mtr_t	mtr;
1795
	mtr_t	mtr2;
1796
	page_t*	header_page;
1797
	ulint	flags;
1798
	ulint	zip_size;
1799
	ulint	page_no;
1800
	page_t*	page;
1801
	page_t*	root;
1802
	page_t*	bitmap_page;
1803
1804
	mtr_start(&mtr);
1805
1806
	/* Acquire the fsp latch before the ibuf header, obeying the latching
1807
	order */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1808
	mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1809
	zip_size = dict_table_flags_to_zip_size(flags);
1810
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1811
	header_page = ibuf_header_page_get(&mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1812
1813
	/* Prevent pessimistic inserts to insert buffer trees for a while */
1814
	mutex_enter(&ibuf_pessimistic_insert_mutex);
1815
1816
	ibuf_enter();
1817
1818
	mutex_enter(&ibuf_mutex);
1819
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1820
	if (!ibuf_data_too_much_free()) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1821
1822
		mutex_exit(&ibuf_mutex);
1823
1824
		ibuf_exit();
1825
1826
		mutex_exit(&ibuf_pessimistic_insert_mutex);
1827
1828
		mtr_commit(&mtr);
1829
1830
		return;
1831
	}
1832
1833
	mtr_start(&mtr2);
1834
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1835
	root = ibuf_tree_root_get(&mtr2);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1836
1837
	page_no = flst_get_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1838
				&mtr2).page;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1839
1840
	/* NOTE that we must release the latch on the ibuf tree root
1841
	because in fseg_free_page we access level 1 pages, and the root
1842
	is a level 2 page. */
1843
1844
	mtr_commit(&mtr2);
1845
	mutex_exit(&ibuf_mutex);
1846
1847
	ibuf_exit();
1848
1849
	/* Since pessimistic inserts were prevented, we know that the
1850
	page is still in the free list. NOTE that also deletes may take
1851
	pages from the free list, but they take them from the start, and
1852
	the free list was so long that they cannot have taken the last
1853
	page from it. */
1854
1855
	fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1856
		       IBUF_SPACE_ID, page_no, &mtr);
1857
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1858
#ifdef UNIV_DEBUG_FILE_ACCESSES
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1859
	buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1860
#endif
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1861
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1862
	ibuf_enter();
1863
1864
	mutex_enter(&ibuf_mutex);
1865
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1866
	root = ibuf_tree_root_get(&mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1867
1868
	ut_ad(page_no == flst_get_last(root + PAGE_HEADER
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1869
				       + PAGE_BTR_IBUF_FREE_LIST, &mtr).page);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1870
1871
	{
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1872
		buf_block_t*	block;
1873
1874
		block = buf_page_get(
1875
			IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
1876
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1877
		buf_block_dbg_add_level(block, SYNC_TREE_NODE);
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
1878
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1879
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1880
		page = buf_block_get_frame(block);
1881
	}
1882
1883
	/* Remove the page from the free list and update the ibuf size data */
1884
1885
	flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
1886
		    page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
1887
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1888
	ibuf->seg_size--;
1889
	ibuf->free_list_len--;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1890
1891
	mutex_exit(&ibuf_pessimistic_insert_mutex);
1892
1893
	/* Set the bit indicating that this page is no more an ibuf tree page
1894
	(level 2 page) */
1895
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1896
	bitmap_page = ibuf_bitmap_get_map_page(
1897
		IBUF_SPACE_ID, page_no, zip_size, &mtr);
1898
1899
	ibuf_bitmap_page_set_bits(
1900
		bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, FALSE, &mtr);
1901
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1902
#ifdef UNIV_DEBUG_FILE_ACCESSES
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1903
	buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1904
#endif
1905
	mtr_commit(&mtr);
1906
1907
	mutex_exit(&ibuf_mutex);
1908
1909
	ibuf_exit();
1910
}
1911
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1912
/***********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1913
Frees excess pages from the ibuf free list. This function is called when an OS
1914
thread calls fsp services to allocate a new file segment, or a new page to a
1915
file segment, and the thread did not own the fsp latch before this call. */
1916
UNIV_INTERN
1917
void
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1918
ibuf_free_excess_pages(void)
1919
/*========================*/
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1920
{
1921
	ulint		i;
1922
1923
#ifdef UNIV_SYNC_DEBUG
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1924
	ut_ad(rw_lock_own(fil_space_get_latch(IBUF_SPACE_ID, NULL),
1925
			  RW_LOCK_EX));
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1926
#endif /* UNIV_SYNC_DEBUG */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1927
1928
	ut_ad(rw_lock_get_x_lock_count(
1929
		fil_space_get_latch(IBUF_SPACE_ID, NULL)) == 1);
1930
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1931
	ut_ad(!ibuf_inside());
1932
1933
	/* NOTE: We require that the thread did not own the latch before,
1934
	because then we know that we can obey the correct latching order
1935
	for ibuf latches */
1936
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1937
	if (!ibuf) {
1938
		/* Not yet initialized; not sure if this is possible, but
1939
		does no harm to check for it. */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1940
1941
		return;
1942
	}
1943
1944
	/* Free at most a few pages at a time, so that we do not delay the
1945
	requested service too much */
1946
1947
	for (i = 0; i < 4; i++) {
1948
1949
		mutex_enter(&ibuf_mutex);
1950
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1951
		if (!ibuf_data_too_much_free()) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1952
1953
			mutex_exit(&ibuf_mutex);
1954
1955
			return;
1956
		}
1957
1958
		mutex_exit(&ibuf_mutex);
1959
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
1960
		ibuf_remove_free_page();
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1961
	}
1962
}
1963
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1964
/*********************************************************************//**
1965
Reads page numbers from a leaf in an ibuf tree.
1966
@return a lower limit for the combined volume of records which will be
1967
merged */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1968
static
1969
ulint
1970
ibuf_get_merge_page_nos(
1971
/*====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1972
	ibool		contract,/*!< in: TRUE if this function is called to
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1973
				contract the tree, FALSE if this is called
1974
				when a single page becomes full and we look
1975
				if it pays to read also nearby pages */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1976
	rec_t*		rec,	/*!< in: record from which we read up and down
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1977
				in the chain of records */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1978
	ulint*		space_ids,/*!< in/out: space id's of the pages */
1979
	ib_int64_t*	space_versions,/*!< in/out: tablespace version
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1980
				timestamps; used to prevent reading in old
1981
				pages after DISCARD + IMPORT tablespace */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1982
	ulint*		page_nos,/*!< in/out: buffer for at least
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1983
				IBUF_MAX_N_PAGES_MERGED many page numbers;
1984
				the page numbers are in an ascending order */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
1985
	ulint*		n_stored)/*!< out: number of page numbers stored to
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
1986
				page_nos in this function */
1987
{
1988
	ulint	prev_page_no;
1989
	ulint	prev_space_id;
1990
	ulint	first_page_no;
1991
	ulint	first_space_id;
1992
	ulint	rec_page_no;
1993
	ulint	rec_space_id;
1994
	ulint	sum_volumes;
1995
	ulint	volume_for_page;
1996
	ulint	rec_volume;
1997
	ulint	limit;
1998
	ulint	n_pages;
1999
2000
	*n_stored = 0;
2001
2002
	limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool->curr_size / 4);
2003
2004
	if (page_rec_is_supremum(rec)) {
2005
2006
		rec = page_rec_get_prev(rec);
2007
	}
2008
2009
	if (page_rec_is_infimum(rec)) {
2010
2011
		rec = page_rec_get_next(rec);
2012
	}
2013
2014
	if (page_rec_is_supremum(rec)) {
2015
2016
		return(0);
2017
	}
2018
2019
	first_page_no = ibuf_rec_get_page_no(rec);
2020
	first_space_id = ibuf_rec_get_space(rec);
2021
	n_pages = 0;
2022
	prev_page_no = 0;
2023
	prev_space_id = 0;
2024
2025
	/* Go backwards from the first rec until we reach the border of the
2026
	'merge area', or the page start or the limit of storeable pages is
2027
	reached */
2028
2029
	while (!page_rec_is_infimum(rec) && UNIV_LIKELY(n_pages < limit)) {
2030
2031
		rec_page_no = ibuf_rec_get_page_no(rec);
2032
		rec_space_id = ibuf_rec_get_space(rec);
2033
2034
		if (rec_space_id != first_space_id
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2035
		    || (rec_page_no / IBUF_MERGE_AREA)
2036
		    != (first_page_no / IBUF_MERGE_AREA)) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2037
2038
			break;
2039
		}
2040
2041
		if (rec_page_no != prev_page_no
2042
		    || rec_space_id != prev_space_id) {
2043
			n_pages++;
2044
		}
2045
2046
		prev_page_no = rec_page_no;
2047
		prev_space_id = rec_space_id;
2048
2049
		rec = page_rec_get_prev(rec);
2050
	}
2051
2052
	rec = page_rec_get_next(rec);
2053
2054
	/* At the loop start there is no prev page; we mark this with a pair
2055
	of space id, page no (0, 0) for which there can never be entries in
2056
	the insert buffer */
2057
2058
	prev_page_no = 0;
2059
	prev_space_id = 0;
2060
	sum_volumes = 0;
2061
	volume_for_page = 0;
2062
2063
	while (*n_stored < limit) {
2064
		if (page_rec_is_supremum(rec)) {
2065
			/* When no more records available, mark this with
2066
			another 'impossible' pair of space id, page no */
2067
			rec_page_no = 1;
2068
			rec_space_id = 0;
2069
		} else {
2070
			rec_page_no = ibuf_rec_get_page_no(rec);
2071
			rec_space_id = ibuf_rec_get_space(rec);
2072
			ut_ad(rec_page_no > IBUF_TREE_ROOT_PAGE_NO);
2073
		}
2074
2075
#ifdef UNIV_IBUF_DEBUG
2076
		ut_a(*n_stored < IBUF_MAX_N_PAGES_MERGED);
2077
#endif
2078
		if ((rec_space_id != prev_space_id
2079
		     || rec_page_no != prev_page_no)
2080
		    && (prev_space_id != 0 || prev_page_no != 0)) {
2081
2082
			if ((prev_page_no == first_page_no
2083
			     && prev_space_id == first_space_id)
2084
			    || contract
2085
			    || (volume_for_page
2086
				> ((IBUF_MERGE_THRESHOLD - 1)
2087
				   * 4 * UNIV_PAGE_SIZE
2088
				   / IBUF_PAGE_SIZE_PER_FREE_SPACE)
2089
				/ IBUF_MERGE_THRESHOLD)) {
2090
2091
				space_ids[*n_stored] = prev_space_id;
2092
				space_versions[*n_stored]
2093
					= fil_space_get_version(prev_space_id);
2094
				page_nos[*n_stored] = prev_page_no;
2095
2096
				(*n_stored)++;
2097
2098
				sum_volumes += volume_for_page;
2099
			}
2100
2101
			if (rec_space_id != first_space_id
2102
			    || rec_page_no / IBUF_MERGE_AREA
2103
			    != first_page_no / IBUF_MERGE_AREA) {
2104
2105
				break;
2106
			}
2107
2108
			volume_for_page = 0;
2109
		}
2110
2111
		if (rec_page_no == 1 && rec_space_id == 0) {
2112
			/* Supremum record */
2113
2114
			break;
2115
		}
2116
2117
		rec_volume = ibuf_rec_get_volume(rec);
2118
2119
		volume_for_page += rec_volume;
2120
2121
		prev_page_no = rec_page_no;
2122
		prev_space_id = rec_space_id;
2123
2124
		rec = page_rec_get_next(rec);
2125
	}
2126
2127
#ifdef UNIV_IBUF_DEBUG
2128
	ut_a(*n_stored <= IBUF_MAX_N_PAGES_MERGED);
2129
#endif
2130
#if 0
2131
	fprintf(stderr, "Ibuf merge batch %lu pages %lu volume\n",
2132
		*n_stored, sum_volumes);
2133
#endif
2134
	return(sum_volumes);
2135
}
2136
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2137
/*********************************************************************//**
2138
Contracts insert buffer trees by reading pages to the buffer pool.
2139
@return a lower limit for the combined size in bytes of entries which
2140
will be merged from ibuf trees to the pages read, 0 if ibuf is
2141
empty */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2142
static
2143
ulint
2144
ibuf_contract_ext(
2145
/*==============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2146
	ulint*	n_pages,/*!< out: number of pages to which merged */
2147
	ibool	sync)	/*!< in: TRUE if the caller wants to wait for the
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2148
			issued read with the highest tablespace address
2149
			to complete */
2150
{
2151
	btr_pcur_t	pcur;
2152
	ulint		page_nos[IBUF_MAX_N_PAGES_MERGED];
2153
	ulint		space_ids[IBUF_MAX_N_PAGES_MERGED];
2154
	ib_int64_t	space_versions[IBUF_MAX_N_PAGES_MERGED];
2155
	ulint		n_stored;
2156
	ulint		sum_sizes;
2157
	mtr_t		mtr;
2158
2159
	*n_pages = 0;
2160
	ut_ad(!ibuf_inside());
2161
2162
	mutex_enter(&ibuf_mutex);
2163
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2164
	if (ibuf->empty) {
2165
ibuf_is_empty:
2166
		mutex_exit(&ibuf_mutex);
2167
2168
		return(0);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2169
	}
2170
2171
	mtr_start(&mtr);
2172
2173
	ibuf_enter();
2174
2175
	/* Open a cursor to a randomly chosen leaf of the tree, at a random
2176
	position within the leaf */
2177
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2178
	btr_pcur_open_at_rnd_pos(ibuf->index, BTR_SEARCH_LEAF, &pcur, &mtr);
2179
2180
	if (page_get_n_recs(btr_pcur_get_page(&pcur)) == 0) {
2181
		/* When the ibuf tree is emptied completely, the last record
2182
		is removed using an optimistic delete and ibuf_size_update
2183
		is not called, causing ibuf->empty to remain FALSE. If we do
2184
		not reset it to TRUE here then database shutdown will hang
2185
		in the loop in ibuf_contract_for_n_pages. */
2186
2187
		ibuf->empty = TRUE;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2188
2189
		ibuf_exit();
2190
2191
		mtr_commit(&mtr);
2192
		btr_pcur_close(&pcur);
2193
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2194
		goto ibuf_is_empty;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2195
	}
2196
2197
	mutex_exit(&ibuf_mutex);
2198
2199
	sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur),
2200
					    space_ids, space_versions,
2201
					    page_nos, &n_stored);
2202
#if 0 /* defined UNIV_IBUF_DEBUG */
2203
	fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n",
2204
		sync, n_stored, sum_sizes);
2205
#endif
2206
	ibuf_exit();
2207
2208
	mtr_commit(&mtr);
2209
	btr_pcur_close(&pcur);
2210
2211
	buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos,
2212
				  n_stored);
2213
	*n_pages = n_stored;
2214
2215
	return(sum_sizes + 1);
2216
}
2217
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2218
/*********************************************************************//**
2219
Contracts insert buffer trees by reading pages to the buffer pool.
2220
@return a lower limit for the combined size in bytes of entries which
2221
will be merged from ibuf trees to the pages read, 0 if ibuf is
2222
empty */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2223
UNIV_INTERN
2224
ulint
2225
ibuf_contract(
2226
/*==========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2227
	ibool	sync)	/*!< in: TRUE if the caller wants to wait for the
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2228
			issued read with the highest tablespace address
2229
			to complete */
2230
{
2231
	ulint	n_pages;
2232
2233
	return(ibuf_contract_ext(&n_pages, sync));
2234
}
2235
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2236
/*********************************************************************//**
2237
Contracts insert buffer trees by reading pages to the buffer pool.
2238
@return a lower limit for the combined size in bytes of entries which
2239
will be merged from ibuf trees to the pages read, 0 if ibuf is
2240
empty */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2241
UNIV_INTERN
2242
ulint
2243
ibuf_contract_for_n_pages(
2244
/*======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2245
	ibool	sync,	/*!< in: TRUE if the caller wants to wait for the
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2246
			issued read with the highest tablespace address
2247
			to complete */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2248
	ulint	n_pages)/*!< in: try to read at least this many pages to
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2249
			the buffer pool and merge the ibuf contents to
2250
			them */
2251
{
2252
	ulint	sum_bytes	= 0;
2253
	ulint	sum_pages	= 0;
2254
	ulint	n_bytes;
2255
	ulint	n_pag2;
2256
2257
	while (sum_pages < n_pages) {
2258
		n_bytes = ibuf_contract_ext(&n_pag2, sync);
2259
2260
		if (n_bytes == 0) {
2261
			return(sum_bytes);
2262
		}
2263
2264
		sum_bytes += n_bytes;
2265
		sum_pages += n_pag2;
2266
	}
2267
2268
	return(sum_bytes);
2269
}
2270
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2271
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2272
Contract insert buffer trees after insert if they are too big. */
2273
UNIV_INLINE
2274
void
2275
ibuf_contract_after_insert(
2276
/*=======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2277
	ulint	entry_size)	/*!< in: size of a record which was inserted
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2278
				into an ibuf tree */
2279
{
2280
	ibool	sync;
2281
	ulint	sum_sizes;
2282
	ulint	size;
2283
2284
	mutex_enter(&ibuf_mutex);
2285
2286
	if (ibuf->size < ibuf->max_size + IBUF_CONTRACT_ON_INSERT_NON_SYNC) {
2287
		mutex_exit(&ibuf_mutex);
2288
2289
		return;
2290
	}
2291
2292
	sync = FALSE;
2293
2294
	if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_ON_INSERT_SYNC) {
2295
2296
		sync = TRUE;
2297
	}
2298
2299
	mutex_exit(&ibuf_mutex);
2300
2301
	/* Contract at least entry_size many bytes */
2302
	sum_sizes = 0;
2303
	size = 1;
2304
2305
	while ((size > 0) && (sum_sizes < entry_size)) {
2306
2307
		size = ibuf_contract(sync);
2308
		sum_sizes += size;
2309
	}
2310
}
2311
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2312
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2313
Gets an upper limit for the combined size of entries buffered in the insert
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2314
buffer for a given page.
2315
@return upper limit for the volume of buffered inserts for the index
2316
page, in bytes; UNIV_PAGE_SIZE, if the entries for the index page span
2317
several pages in the insert buffer */
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
2318
static
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2319
ulint
2320
ibuf_get_volume_buffered(
2321
/*=====================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2322
	btr_pcur_t*	pcur,	/*!< in: pcur positioned at a place in an
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2323
				insert buffer tree where we would insert an
2324
				entry for the index page whose number is
2325
				page_no, latch mode has to be BTR_MODIFY_PREV
2326
				or BTR_MODIFY_TREE */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2327
	ulint		space,	/*!< in: space id */
2328
	ulint		page_no,/*!< in: page number of an index page */
2329
	mtr_t*		mtr)	/*!< in: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2330
{
2331
	ulint	volume;
2332
	rec_t*	rec;
2333
	page_t*	page;
2334
	ulint	prev_page_no;
2335
	page_t*	prev_page;
2336
	ulint	next_page_no;
2337
	page_t*	next_page;
2338
2339
	ut_a(trx_sys_multiple_tablespace_format);
2340
2341
	ut_ad((pcur->latch_mode == BTR_MODIFY_PREV)
2342
	      || (pcur->latch_mode == BTR_MODIFY_TREE));
2343
2344
	/* Count the volume of records earlier in the alphabetical order than
2345
	pcur */
2346
2347
	volume = 0;
2348
2349
	rec = btr_pcur_get_rec(pcur);
2350
	page = page_align(rec);
2351
2352
	if (page_rec_is_supremum(rec)) {
2353
		rec = page_rec_get_prev(rec);
2354
	}
2355
2356
	for (;;) {
2357
		if (page_rec_is_infimum(rec)) {
2358
2359
			break;
2360
		}
2361
2362
		if (page_no != ibuf_rec_get_page_no(rec)
2363
		    || space != ibuf_rec_get_space(rec)) {
2364
2365
			goto count_later;
2366
		}
2367
2368
		volume += ibuf_rec_get_volume(rec);
2369
2370
		rec = page_rec_get_prev(rec);
2371
	}
2372
2373
	/* Look at the previous page */
2374
2375
	prev_page_no = btr_page_get_prev(page, mtr);
2376
2377
	if (prev_page_no == FIL_NULL) {
2378
2379
		goto count_later;
2380
	}
2381
2382
	{
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2383
		buf_block_t*	block;
2384
2385
		block = buf_page_get(
2386
			IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH, mtr);
2387
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2388
		buf_block_dbg_add_level(block, SYNC_TREE_NODE);
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
2389
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2390
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2391
		prev_page = buf_block_get_frame(block);
2392
	}
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2393
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2394
#ifdef UNIV_BTR_DEBUG
2395
	ut_a(btr_page_get_next(prev_page, mtr)
2396
	     == page_get_page_no(page));
2397
#endif /* UNIV_BTR_DEBUG */
2398
2399
	rec = page_get_supremum_rec(prev_page);
2400
	rec = page_rec_get_prev(rec);
2401
2402
	for (;;) {
2403
		if (page_rec_is_infimum(rec)) {
2404
2405
			/* We cannot go to yet a previous page, because we
2406
			do not have the x-latch on it, and cannot acquire one
2407
			because of the latching order: we have to give up */
2408
2409
			return(UNIV_PAGE_SIZE);
2410
		}
2411
2412
		if (page_no != ibuf_rec_get_page_no(rec)
2413
		    || space != ibuf_rec_get_space(rec)) {
2414
2415
			goto count_later;
2416
		}
2417
2418
		volume += ibuf_rec_get_volume(rec);
2419
2420
		rec = page_rec_get_prev(rec);
2421
	}
2422
2423
count_later:
2424
	rec = btr_pcur_get_rec(pcur);
2425
2426
	if (!page_rec_is_supremum(rec)) {
2427
		rec = page_rec_get_next(rec);
2428
	}
2429
2430
	for (;;) {
2431
		if (page_rec_is_supremum(rec)) {
2432
2433
			break;
2434
		}
2435
2436
		if (page_no != ibuf_rec_get_page_no(rec)
2437
		    || space != ibuf_rec_get_space(rec)) {
2438
2439
			return(volume);
2440
		}
2441
2442
		volume += ibuf_rec_get_volume(rec);
2443
2444
		rec = page_rec_get_next(rec);
2445
	}
2446
2447
	/* Look at the next page */
2448
2449
	next_page_no = btr_page_get_next(page, mtr);
2450
2451
	if (next_page_no == FIL_NULL) {
2452
2453
		return(volume);
2454
	}
2455
2456
	{
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2457
		buf_block_t*	block;
2458
2459
		block = buf_page_get(
2460
			IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH, mtr);
2461
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2462
		buf_block_dbg_add_level(block, SYNC_TREE_NODE);
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
2463
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2464
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2465
		next_page = buf_block_get_frame(block);
2466
	}
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2467
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2468
#ifdef UNIV_BTR_DEBUG
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2469
	ut_a(btr_page_get_prev(next_page, mtr) == page_get_page_no(page));
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2470
#endif /* UNIV_BTR_DEBUG */
2471
2472
	rec = page_get_infimum_rec(next_page);
2473
	rec = page_rec_get_next(rec);
2474
2475
	for (;;) {
2476
		if (page_rec_is_supremum(rec)) {
2477
2478
			/* We give up */
2479
2480
			return(UNIV_PAGE_SIZE);
2481
		}
2482
2483
		if (page_no != ibuf_rec_get_page_no(rec)
2484
		    || space != ibuf_rec_get_space(rec)) {
2485
2486
			return(volume);
2487
		}
2488
2489
		volume += ibuf_rec_get_volume(rec);
2490
2491
		rec = page_rec_get_next(rec);
2492
	}
2493
}
2494
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2495
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2496
Reads the biggest tablespace id from the high end of the insert buffer
2497
tree and updates the counter in fil_system. */
2498
UNIV_INTERN
2499
void
2500
ibuf_update_max_tablespace_id(void)
2501
/*===============================*/
2502
{
2503
	ulint		max_space_id;
2504
	const rec_t*	rec;
2505
	const byte*	field;
2506
	ulint		len;
2507
	btr_pcur_t	pcur;
2508
	mtr_t		mtr;
2509
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2510
	ut_a(!dict_table_is_comp(ibuf->index->table));
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2511
2512
	ibuf_enter();
2513
2514
	mtr_start(&mtr);
2515
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2516
	btr_pcur_open_at_index_side(
2517
		FALSE, ibuf->index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
2518
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2519
	btr_pcur_move_to_prev(&pcur, &mtr);
2520
2521
	if (btr_pcur_is_before_first_on_page(&pcur)) {
2522
		/* The tree is empty */
2523
2524
		max_space_id = 0;
2525
	} else {
2526
		rec = btr_pcur_get_rec(&pcur);
2527
2528
		field = rec_get_nth_field_old(rec, 0, &len);
2529
2530
		ut_a(len == 4);
2531
2532
		max_space_id = mach_read_from_4(field);
2533
	}
2534
2535
	mtr_commit(&mtr);
2536
	ibuf_exit();
2537
2538
	/* printf("Maximum space id in insert buffer %lu\n", max_space_id); */
2539
2540
	fil_set_max_space_id_if_bigger(max_space_id);
2541
}
2542
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2543
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2544
Makes an index insert to the insert buffer, instead of directly to the disk
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2545
page, if this is possible.
2546
@return	DB_SUCCESS, DB_FAIL, DB_STRONG_FAIL */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2547
static
2548
ulint
2549
ibuf_insert_low(
2550
/*============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2551
	ulint		mode,	/*!< in: BTR_MODIFY_PREV or BTR_MODIFY_TREE */
2552
	const dtuple_t*	entry,	/*!< in: index entry to insert */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2553
	ulint		entry_size,
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2554
				/*!< in: rec_get_converted_size(index, entry) */
2555
	dict_index_t*	index,	/*!< in: index where to insert; must not be
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2556
				unique or clustered */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2557
	ulint		space,	/*!< in: space id where to insert */
2558
	ulint		zip_size,/*!< in: compressed page size in bytes, or 0 */
2559
	ulint		page_no,/*!< in: page number where to insert */
2560
	que_thr_t*	thr)	/*!< in: query thread */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2561
{
2562
	big_rec_t*	dummy_big_rec;
2563
	btr_pcur_t	pcur;
2564
	btr_cur_t*	cursor;
2565
	dtuple_t*	ibuf_entry;
2566
	mem_heap_t*	heap;
2567
	ulint		buffered;
2568
	rec_t*		ins_rec;
2569
	ibool		old_bit_value;
2570
	page_t*		bitmap_page;
2571
	page_t*		root;
2572
	ulint		err;
2573
	ibool		do_merge;
2574
	ulint		space_ids[IBUF_MAX_N_PAGES_MERGED];
2575
	ib_int64_t	space_versions[IBUF_MAX_N_PAGES_MERGED];
2576
	ulint		page_nos[IBUF_MAX_N_PAGES_MERGED];
2577
	ulint		n_stored;
2578
	ulint		bits;
2579
	mtr_t		mtr;
2580
	mtr_t		bitmap_mtr;
2581
2582
	ut_a(!dict_index_is_clust(index));
2583
	ut_ad(dtuple_check_typed(entry));
2584
	ut_ad(ut_is_2pow(zip_size));
2585
2586
	ut_a(trx_sys_multiple_tablespace_format);
2587
2588
	do_merge = FALSE;
2589
2590
	mutex_enter(&ibuf_mutex);
2591
2592
	if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_DO_NOT_INSERT) {
2593
		/* Insert buffer is now too big, contract it but do not try
2594
		to insert */
2595
2596
		mutex_exit(&ibuf_mutex);
2597
2598
#ifdef UNIV_IBUF_DEBUG
2599
		fputs("Ibuf too big\n", stderr);
2600
#endif
2601
		/* Use synchronous contract (== TRUE) */
2602
		ibuf_contract(TRUE);
2603
2604
		return(DB_STRONG_FAIL);
2605
	}
2606
2607
	mutex_exit(&ibuf_mutex);
2608
2609
	if (mode == BTR_MODIFY_TREE) {
2610
		mutex_enter(&ibuf_pessimistic_insert_mutex);
2611
2612
		ibuf_enter();
2613
2614
		mutex_enter(&ibuf_mutex);
2615
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2616
		while (!ibuf_data_enough_free_for_insert()) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2617
2618
			mutex_exit(&ibuf_mutex);
2619
2620
			ibuf_exit();
2621
2622
			mutex_exit(&ibuf_pessimistic_insert_mutex);
2623
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2624
			err = ibuf_add_free_page();
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2625
2626
			if (err == DB_STRONG_FAIL) {
2627
2628
				return(err);
2629
			}
2630
2631
			mutex_enter(&ibuf_pessimistic_insert_mutex);
2632
2633
			ibuf_enter();
2634
2635
			mutex_enter(&ibuf_mutex);
2636
		}
2637
	} else {
2638
		ibuf_enter();
2639
	}
2640
2641
	heap = mem_heap_create(512);
2642
2643
	/* Build the entry which contains the space id and the page number as
2644
	the first fields and the type information for other fields, and which
2645
	will be inserted to the insert buffer. */
2646
2647
	ibuf_entry = ibuf_entry_build(index, entry, space, page_no, heap);
2648
2649
	/* Open a cursor to the insert buffer tree to calculate if we can add
2650
	the new entry to it without exceeding the free space limit for the
2651
	page. */
2652
2653
	mtr_start(&mtr);
2654
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2655
	btr_pcur_open(ibuf->index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2656
2657
	/* Find out the volume of already buffered inserts for the same index
2658
	page */
2659
	buffered = ibuf_get_volume_buffered(&pcur, space, page_no, &mtr);
2660
2661
#ifdef UNIV_IBUF_COUNT_DEBUG
2662
	ut_a((buffered == 0) || ibuf_count_get(space, page_no));
2663
#endif
2664
	mtr_start(&bitmap_mtr);
2665
2666
	bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
2667
					       zip_size, &bitmap_mtr);
2668
2669
	/* We check if the index page is suitable for buffered entries */
2670
2671
	if (buf_page_peek(space, page_no)
2672
	    || lock_rec_expl_exist_on_page(space, page_no)) {
2673
		err = DB_STRONG_FAIL;
2674
2675
		mtr_commit(&bitmap_mtr);
2676
2677
		goto function_exit;
2678
	}
2679
2680
	bits = ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size,
2681
					 IBUF_BITMAP_FREE, &bitmap_mtr);
2682
2683
	if (buffered + entry_size + page_dir_calc_reserved_space(1)
2684
	    > ibuf_index_page_calc_free_from_bits(zip_size, bits)) {
2685
		mtr_commit(&bitmap_mtr);
2686
2687
		/* It may not fit */
2688
		err = DB_STRONG_FAIL;
2689
2690
		do_merge = TRUE;
2691
2692
		ibuf_get_merge_page_nos(FALSE, btr_pcur_get_rec(&pcur),
2693
					space_ids, space_versions,
2694
					page_nos, &n_stored);
2695
		goto function_exit;
2696
	}
2697
2698
	/* Set the bitmap bit denoting that the insert buffer contains
2699
	buffered entries for this index page, if the bit is not set yet */
2700
2701
	old_bit_value = ibuf_bitmap_page_get_bits(
2702
		bitmap_page, page_no, zip_size,
2703
		IBUF_BITMAP_BUFFERED, &bitmap_mtr);
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2704
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2705
	if (!old_bit_value) {
2706
		ibuf_bitmap_page_set_bits(bitmap_page, page_no, zip_size,
2707
					  IBUF_BITMAP_BUFFERED, TRUE,
2708
					  &bitmap_mtr);
2709
	}
2710
2711
	mtr_commit(&bitmap_mtr);
2712
2713
	cursor = btr_pcur_get_btr_cur(&pcur);
2714
2715
	if (mode == BTR_MODIFY_PREV) {
2716
		err = btr_cur_optimistic_insert(BTR_NO_LOCKING_FLAG, cursor,
2717
						ibuf_entry, &ins_rec,
2718
						&dummy_big_rec, 0, thr, &mtr);
2719
		if (err == DB_SUCCESS) {
2720
			/* Update the page max trx id field */
2721
			page_update_max_trx_id(btr_cur_get_block(cursor), NULL,
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2722
					       thr_get_trx(thr)->id, &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2723
		}
2724
	} else {
2725
		ut_ad(mode == BTR_MODIFY_TREE);
2726
2727
		/* We acquire an x-latch to the root page before the insert,
2728
		because a pessimistic insert releases the tree x-latch,
2729
		which would cause the x-latching of the root after that to
2730
		break the latching order. */
2731
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2732
		root = ibuf_tree_root_get(&mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2733
2734
		err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG
2735
						 | BTR_NO_UNDO_LOG_FLAG,
2736
						 cursor,
2737
						 ibuf_entry, &ins_rec,
2738
						 &dummy_big_rec, 0, thr, &mtr);
2739
		if (err == DB_SUCCESS) {
2740
			/* Update the page max trx id field */
2741
			page_update_max_trx_id(btr_cur_get_block(cursor), NULL,
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2742
					       thr_get_trx(thr)->id, &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2743
		}
2744
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2745
		ibuf_size_update(root, &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2746
	}
2747
2748
function_exit:
2749
#ifdef UNIV_IBUF_COUNT_DEBUG
2750
	if (err == DB_SUCCESS) {
2751
		fprintf(stderr,
2752
			"Incrementing ibuf count of space %lu page %lu\n"
2753
			"from %lu by 1\n", space, page_no,
2754
			ibuf_count_get(space, page_no));
2755
2756
		ibuf_count_set(space, page_no,
2757
			       ibuf_count_get(space, page_no) + 1);
2758
	}
2759
#endif
2760
	if (mode == BTR_MODIFY_TREE) {
2761
2762
		mutex_exit(&ibuf_mutex);
2763
		mutex_exit(&ibuf_pessimistic_insert_mutex);
2764
	}
2765
2766
	mtr_commit(&mtr);
2767
	btr_pcur_close(&pcur);
2768
	ibuf_exit();
2769
2770
	mem_heap_free(heap);
2771
2772
	if (err == DB_SUCCESS) {
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
2773
		mutex_enter(&ibuf_mutex);
2774
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2775
		ibuf->empty = FALSE;
2776
		ibuf->n_inserts++;
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
2777
2778
		mutex_exit(&ibuf_mutex);
2779
2780
		if (mode == BTR_MODIFY_TREE) {
2781
			ibuf_contract_after_insert(entry_size);
2782
		}
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2783
	}
2784
2785
	if (do_merge) {
2786
#ifdef UNIV_IBUF_DEBUG
2787
		ut_a(n_stored <= IBUF_MAX_N_PAGES_MERGED);
2788
#endif
2789
		buf_read_ibuf_merge_pages(FALSE, space_ids, space_versions,
2790
					  page_nos, n_stored);
2791
	}
2792
2793
	return(err);
2794
}
2795
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2796
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2797
Makes an index insert to the insert buffer, instead of directly to the disk
2798
page, if this is possible. Does not do insert if the index is clustered
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2799
or unique.
2800
@return	TRUE if success */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2801
UNIV_INTERN
2802
ibool
2803
ibuf_insert(
2804
/*========*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2805
	const dtuple_t*	entry,	/*!< in: index entry to insert */
2806
	dict_index_t*	index,	/*!< in: index where to insert */
2807
	ulint		space,	/*!< in: space id where to insert */
2808
	ulint		zip_size,/*!< in: compressed page size in bytes, or 0 */
2809
	ulint		page_no,/*!< in: page number where to insert */
2810
	que_thr_t*	thr)	/*!< in: query thread */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2811
{
2812
	ulint	err;
2813
	ulint	entry_size;
2814
2815
	ut_a(trx_sys_multiple_tablespace_format);
2816
	ut_ad(dtuple_check_typed(entry));
2817
	ut_ad(ut_is_2pow(zip_size));
2818
2819
	ut_a(!dict_index_is_clust(index));
2820
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
2821
	switch (UNIV_EXPECT(ibuf_use, IBUF_USE_INSERT)) {
2822
	case IBUF_USE_NONE:
2823
		return(FALSE);
2824
	case IBUF_USE_INSERT:
2825
		goto do_insert;
2826
	case IBUF_USE_COUNT:
2827
		break;
2828
	}
2829
2830
	ut_error; /* unknown value of ibuf_use */
2831
2832
do_insert:
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2833
	entry_size = rec_get_converted_size(index, entry, 0);
2834
2835
	if (entry_size
2836
	    >= (page_get_free_space_of_empty(dict_table_is_comp(index->table))
2837
		/ 2)) {
2838
		return(FALSE);
2839
	}
2840
2841
	err = ibuf_insert_low(BTR_MODIFY_PREV, entry, entry_size,
2842
			      index, space, zip_size, page_no, thr);
2843
	if (err == DB_FAIL) {
2844
		err = ibuf_insert_low(BTR_MODIFY_TREE, entry, entry_size,
2845
				      index, space, zip_size, page_no, thr);
2846
	}
2847
2848
	if (err == DB_SUCCESS) {
2849
#ifdef UNIV_IBUF_DEBUG
2850
		/* fprintf(stderr, "Ibuf insert for page no %lu of index %s\n",
2851
		page_no, index->name); */
2852
#endif
2853
		return(TRUE);
2854
2855
	} else {
2856
		ut_a(err == DB_STRONG_FAIL);
2857
2858
		return(FALSE);
2859
	}
2860
}
2861
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2862
/********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2863
During merge, inserts to an index page a secondary index entry extracted
2864
from the insert buffer. */
2865
static
2866
void
2867
ibuf_insert_to_index_page(
2868
/*======================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2869
	dtuple_t*	entry,	/*!< in: buffered entry to insert */
2870
	buf_block_t*	block,	/*!< in/out: index page where the buffered entry
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2871
				should be placed */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2872
	dict_index_t*	index,	/*!< in: record descriptor */
2873
	mtr_t*		mtr)	/*!< in: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2874
{
2875
	page_cur_t	page_cur;
2876
	ulint		low_match;
2877
	page_t*		page		= buf_block_get_frame(block);
2878
	rec_t*		rec;
2879
	page_t*		bitmap_page;
2880
	ulint		old_bits;
2881
2882
	ut_ad(ibuf_inside());
2883
	ut_ad(dtuple_check_typed(entry));
2884
2885
	if (UNIV_UNLIKELY(dict_table_is_comp(index->table)
2886
			  != (ibool)!!page_is_comp(page))) {
2887
		fputs("InnoDB: Trying to insert a record from"
2888
		      " the insert buffer to an index page\n"
2889
		      "InnoDB: but the 'compact' flag does not match!\n",
2890
		      stderr);
2891
		goto dump;
2892
	}
2893
2894
	rec = page_rec_get_next(page_get_infimum_rec(page));
2895
2896
	if (UNIV_UNLIKELY(rec_get_n_fields(rec, index)
2897
			  != dtuple_get_n_fields(entry))) {
2898
		fputs("InnoDB: Trying to insert a record from"
2899
		      " the insert buffer to an index page\n"
2900
		      "InnoDB: but the number of fields does not match!\n",
2901
		      stderr);
2902
dump:
2903
		buf_page_print(page, 0);
2904
2905
		dtuple_print(stderr, entry);
2906
2907
		fputs("InnoDB: The table where where"
2908
		      " this index record belongs\n"
2909
		      "InnoDB: is now probably corrupt."
2910
		      " Please run CHECK TABLE on\n"
2911
		      "InnoDB: your tables.\n"
2912
		      "InnoDB: Submit a detailed bug report to"
2913
		      " http://bugs.mysql.com!\n", stderr);
2914
2915
		return;
2916
	}
2917
2918
	low_match = page_cur_search(block, index, entry,
2919
				    PAGE_CUR_LE, &page_cur);
2920
2921
	if (low_match == dtuple_get_n_fields(entry)) {
2922
		page_zip_des_t*	page_zip;
2923
2924
		rec = page_cur_get_rec(&page_cur);
2925
		page_zip = buf_block_get_page_zip(block);
2926
2927
		btr_cur_del_unmark_for_ibuf(rec, page_zip, mtr);
2928
	} else {
2929
		rec = page_cur_tuple_insert(&page_cur, entry, index, 0, mtr);
2930
2931
		if (UNIV_LIKELY(rec != NULL)) {
2932
			return;
2933
		}
2934
2935
		/* If the record did not fit, reorganize */
2936
2937
		btr_page_reorganize(block, index, mtr);
2938
		page_cur_search(block, index, entry, PAGE_CUR_LE, &page_cur);
2939
2940
		/* This time the record must fit */
2941
		if (UNIV_UNLIKELY
2942
		    (!page_cur_tuple_insert(&page_cur, entry, index,
2943
					    0, mtr))) {
2944
			ulint	space;
2945
			ulint	page_no;
2946
			ulint	zip_size;
2947
2948
			ut_print_timestamp(stderr);
2949
2950
			fprintf(stderr,
2951
				"  InnoDB: Error: Insert buffer insert"
2952
				" fails; page free %lu,"
2953
				" dtuple size %lu\n",
2954
				(ulong) page_get_max_insert_size(
2955
					page, 1),
2956
				(ulong) rec_get_converted_size(
2957
					index, entry, 0));
2958
			fputs("InnoDB: Cannot insert index record ",
2959
			      stderr);
2960
			dtuple_print(stderr, entry);
2961
			fputs("\nInnoDB: The table where"
2962
			      " this index record belongs\n"
2963
			      "InnoDB: is now probably corrupt."
2964
			      " Please run CHECK TABLE on\n"
2965
			      "InnoDB: that table.\n", stderr);
2966
2967
			space = page_get_space_id(page);
2968
			zip_size = buf_block_get_zip_size(block);
2969
			page_no = page_get_page_no(page);
2970
2971
			bitmap_page = ibuf_bitmap_get_map_page(
2972
				space, page_no, zip_size, mtr);
2973
			old_bits = ibuf_bitmap_page_get_bits(
2974
				bitmap_page, page_no, zip_size,
2975
				IBUF_BITMAP_FREE, mtr);
2976
2977
			fprintf(stderr,
2978
				"InnoDB: space %lu, page %lu,"
2979
				" zip_size %lu, bitmap bits %lu\n",
2980
				(ulong) space, (ulong) page_no,
2981
				(ulong) zip_size, (ulong) old_bits);
2982
2983
			fputs("InnoDB: Submit a detailed bug report"
2984
			      " to http://bugs.mysql.com\n", stderr);
2985
		}
2986
	}
2987
}
2988
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2989
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2990
Deletes from ibuf the record on which pcur is positioned. If we have to
2991
resort to a pessimistic delete, this function commits mtr and closes
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2992
the cursor.
2993
@return	TRUE if mtr was committed and pcur closed in this operation */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
2994
static
2995
ibool
2996
ibuf_delete_rec(
2997
/*============*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
2998
	ulint		space,	/*!< in: space id */
2999
	ulint		page_no,/*!< in: index page number where the record
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3000
				should belong */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3001
	btr_pcur_t*	pcur,	/*!< in: pcur positioned on the record to
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3002
				delete, having latch mode BTR_MODIFY_LEAF */
3003
	const dtuple_t*	search_tuple,
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3004
				/*!< in: search tuple for entries of page_no */
3005
	mtr_t*		mtr)	/*!< in: mtr */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3006
{
3007
	ibool		success;
3008
	page_t*		root;
3009
	ulint		err;
3010
3011
	ut_ad(ibuf_inside());
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
3012
	ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur)));
3013
	ut_ad(ibuf_rec_get_page_no(btr_pcur_get_rec(pcur)) == page_no);
3014
	ut_ad(ibuf_rec_get_space(btr_pcur_get_rec(pcur)) == space);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3015
3016
	success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr);
3017
3018
	if (success) {
3019
#ifdef UNIV_IBUF_COUNT_DEBUG
3020
		fprintf(stderr,
3021
			"Decrementing ibuf count of space %lu page %lu\n"
3022
			"from %lu by 1\n", space, page_no,
3023
			ibuf_count_get(space, page_no));
3024
		ibuf_count_set(space, page_no,
3025
			       ibuf_count_get(space, page_no) - 1);
3026
#endif
3027
		return(FALSE);
3028
	}
3029
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
3030
	ut_ad(page_rec_is_user_rec(btr_pcur_get_rec(pcur)));
3031
	ut_ad(ibuf_rec_get_page_no(btr_pcur_get_rec(pcur)) == page_no);
3032
	ut_ad(ibuf_rec_get_space(btr_pcur_get_rec(pcur)) == space);
3033
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3034
	/* We have to resort to a pessimistic delete from ibuf */
3035
	btr_pcur_store_position(pcur, mtr);
3036
3037
	btr_pcur_commit_specify_mtr(pcur, mtr);
3038
3039
	mutex_enter(&ibuf_mutex);
3040
3041
	mtr_start(mtr);
3042
3043
	success = btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr);
3044
3045
	if (!success) {
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
3046
		if (fil_space_get_flags(space) == ULINT_UNDEFINED) {
3047
			/* The tablespace has been dropped.  It is possible
3048
			that another thread has deleted the insert buffer
3049
			entry.  Do not complain. */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3050
			goto commit_and_exit;
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
3051
		}
3052
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3053
		fprintf(stderr,
3054
			"InnoDB: ERROR: Submit the output to"
3055
			" http://bugs.mysql.com\n"
3056
			"InnoDB: ibuf cursor restoration fails!\n"
3057
			"InnoDB: ibuf record inserted to page %lu\n",
3058
			(ulong) page_no);
3059
		fflush(stderr);
3060
3061
		rec_print_old(stderr, btr_pcur_get_rec(pcur));
3062
		rec_print_old(stderr, pcur->old_rec);
3063
		dtuple_print(stderr, search_tuple);
3064
3065
		rec_print_old(stderr,
3066
			      page_rec_get_next(btr_pcur_get_rec(pcur)));
3067
		fflush(stderr);
3068
3069
		btr_pcur_commit_specify_mtr(pcur, mtr);
3070
3071
		fputs("InnoDB: Validating insert buffer tree:\n", stderr);
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3072
		if (!btr_validate_index(ibuf->index, NULL)) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3073
			ut_error;
3074
		}
3075
3076
		fprintf(stderr, "InnoDB: ibuf tree ok\n");
3077
		fflush(stderr);
3078
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
3079
		goto func_exit;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3080
	}
3081
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3082
	root = ibuf_tree_root_get(mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3083
3084
	btr_cur_pessimistic_delete(&err, TRUE, btr_pcur_get_btr_cur(pcur),
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
3085
				   RB_NONE, mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3086
	ut_a(err == DB_SUCCESS);
3087
3088
#ifdef UNIV_IBUF_COUNT_DEBUG
3089
	ibuf_count_set(space, page_no, ibuf_count_get(space, page_no) - 1);
3090
#endif
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3091
	ibuf_size_update(root, mtr);
3092
3093
commit_and_exit:
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3094
	btr_pcur_commit_specify_mtr(pcur, mtr);
3095
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
3096
func_exit:
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3097
	btr_pcur_close(pcur);
3098
3099
	mutex_exit(&ibuf_mutex);
3100
3101
	return(TRUE);
3102
}
3103
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3104
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3105
When an index page is read from a disk to the buffer pool, this function
3106
inserts to the page the possible index entries buffered in the insert buffer.
3107
The entries are deleted from the insert buffer. If the page is not read, but
3108
created in the buffer pool, this function deletes its buffered entries from
3109
the insert buffer; there can exist entries for such a page if the page
3110
belonged to an index which subsequently was dropped. */
3111
UNIV_INTERN
3112
void
3113
ibuf_merge_or_delete_for_page(
3114
/*==========================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3115
	buf_block_t*	block,	/*!< in: if page has been read from
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3116
				disk, pointer to the page x-latched,
3117
				else NULL */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3118
	ulint		space,	/*!< in: space id of the index page */
3119
	ulint		page_no,/*!< in: page number of the index page */
3120
	ulint		zip_size,/*!< in: compressed page size in bytes,
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3121
				or 0 */
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3122
	ibool		update_ibuf_bitmap)/*!< in: normally this is set
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3123
				to TRUE, but if we have deleted or are
3124
				deleting the tablespace, then we
3125
				naturally do not want to update a
3126
				non-existent bitmap page */
3127
{
3128
	mem_heap_t*	heap;
3129
	btr_pcur_t	pcur;
3130
	dtuple_t*	search_tuple;
3131
	ulint		n_inserts;
3132
#ifdef UNIV_IBUF_DEBUG
3133
	ulint		volume;
3134
#endif
3135
	page_zip_des_t*	page_zip		= NULL;
3136
	ibool		tablespace_being_deleted = FALSE;
3137
	ibool		corruption_noticed	= FALSE;
3138
	mtr_t		mtr;
3139
3140
	ut_ad(!block || buf_block_get_space(block) == space);
3141
	ut_ad(!block || buf_block_get_page_no(block) == page_no);
3142
	ut_ad(!block || buf_block_get_zip_size(block) == zip_size);
3143
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3144
	if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE
3145
	    || trx_sys_hdr_page(space, page_no)) {
3146
		return;
3147
	}
3148
3149
	/* We cannot refer to zip_size in the following, because
3150
	zip_size is passed as ULINT_UNDEFINED (it is unknown) when
3151
	buf_read_ibuf_merge_pages() is merging (discarding) changes
3152
	for a dropped tablespace.  When block != NULL or
3153
	update_ibuf_bitmap is specified, the zip_size must be known.
3154
	That is why we will repeat the check below, with zip_size in
3155
	place of 0.  Passing zip_size as 0 assumes that the
3156
	uncompressed page size always is a power-of-2 multiple of the
3157
	compressed page size. */
3158
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3159
	if (ibuf_fixed_addr_page(space, 0, page_no)
3160
	    || fsp_descr_page(0, page_no)) {
3161
		return;
3162
	}
3163
3164
	if (UNIV_LIKELY(update_ibuf_bitmap)) {
3165
		ut_a(ut_is_2pow(zip_size));
3166
3167
		if (ibuf_fixed_addr_page(space, zip_size, page_no)
3168
		    || fsp_descr_page(zip_size, page_no)) {
3169
			return;
3170
		}
3171
3172
		/* If the following returns FALSE, we get the counter
3173
		incremented, and must decrement it when we leave this
3174
		function. When the counter is > 0, that prevents tablespace
3175
		from being dropped. */
3176
3177
		tablespace_being_deleted = fil_inc_pending_ibuf_merges(space);
3178
3179
		if (UNIV_UNLIKELY(tablespace_being_deleted)) {
3180
			/* Do not try to read the bitmap page from space;
3181
			just delete the ibuf records for the page */
3182
3183
			block = NULL;
3184
			update_ibuf_bitmap = FALSE;
3185
		} else {
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3186
			page_t*	bitmap_page;
3187
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3188
			mtr_start(&mtr);
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3189
3190
			bitmap_page = ibuf_bitmap_get_map_page(
3191
				space, page_no, zip_size, &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3192
3193
			if (!ibuf_bitmap_page_get_bits(bitmap_page, page_no,
3194
						       zip_size,
3195
						       IBUF_BITMAP_BUFFERED,
3196
						       &mtr)) {
3197
				/* No inserts buffered for this page */
3198
				mtr_commit(&mtr);
3199
3200
				if (!tablespace_being_deleted) {
3201
					fil_decr_pending_ibuf_merges(space);
3202
				}
3203
3204
				return;
3205
			}
3206
			mtr_commit(&mtr);
3207
		}
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3208
	} else if (block
3209
		   && (ibuf_fixed_addr_page(space, zip_size, page_no)
3210
		      || fsp_descr_page(zip_size, page_no))) {
3211
3212
		return;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3213
	}
3214
3215
	ibuf_enter();
3216
3217
	heap = mem_heap_create(512);
3218
3219
	if (!trx_sys_multiple_tablespace_format) {
3220
		ut_a(trx_doublewrite_must_reset_space_ids);
3221
		search_tuple = ibuf_search_tuple_build(space, page_no, heap);
3222
	} else {
3223
		search_tuple = ibuf_new_search_tuple_build(space, page_no,
3224
							   heap);
3225
	}
3226
3227
	if (block) {
3228
		/* Move the ownership of the x-latch on the page to this OS
3229
		thread, so that we can acquire a second x-latch on it. This
3230
		is needed for the insert operations to the index page to pass
3231
		the debug checks. */
3232
3233
		rw_lock_x_lock_move_ownership(&(block->lock));
3234
		page_zip = buf_block_get_page_zip(block);
3235
3236
		if (UNIV_UNLIKELY(fil_page_get_type(block->frame)
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
3237
				  != FIL_PAGE_INDEX)
3238
		    || UNIV_UNLIKELY(!page_is_leaf(block->frame))) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3239
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3240
			page_t*	bitmap_page;
3241
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3242
			corruption_noticed = TRUE;
3243
3244
			ut_print_timestamp(stderr);
3245
3246
			mtr_start(&mtr);
3247
3248
			fputs("  InnoDB: Dump of the ibuf bitmap page:\n",
3249
			      stderr);
3250
3251
			bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
3252
							       zip_size, &mtr);
3253
			buf_page_print(bitmap_page, 0);
3254
3255
			mtr_commit(&mtr);
3256
3257
			fputs("\nInnoDB: Dump of the page:\n", stderr);
3258
3259
			buf_page_print(block->frame, 0);
3260
3261
			fprintf(stderr,
3262
				"InnoDB: Error: corruption in the tablespace."
3263
				" Bitmap shows insert\n"
3264
				"InnoDB: buffer records to page n:o %lu"
3265
				" though the page\n"
3266
				"InnoDB: type is %lu, which is"
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
3267
				" not an index leaf page!\n"
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3268
				"InnoDB: We try to resolve the problem"
3269
				" by skipping the insert buffer\n"
3270
				"InnoDB: merge for this page."
3271
				" Please run CHECK TABLE on your tables\n"
3272
				"InnoDB: to determine if they are corrupt"
3273
				" after this.\n\n"
3274
				"InnoDB: Please submit a detailed bug report"
3275
				" to http://bugs.mysql.com\n\n",
3276
				(ulong) page_no,
3277
				(ulong)
3278
				fil_page_get_type(block->frame));
3279
		}
3280
	}
3281
3282
	n_inserts = 0;
3283
#ifdef UNIV_IBUF_DEBUG
3284
	volume = 0;
3285
#endif
3286
loop:
3287
	mtr_start(&mtr);
3288
3289
	if (block) {
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3290
		ibool success;
3291
3292
		success = buf_page_get_known_nowait(
3293
			RW_X_LATCH, block,
3294
			BUF_KEEP_OLD, __FILE__, __LINE__, &mtr);
3295
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3296
		ut_a(success);
641.2.1 by Monty Taylor
InnoDB Plugin 1.0.2
3297
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3298
		buf_block_dbg_add_level(block, SYNC_TREE_NODE);
3299
	}
3300
3301
	/* Position pcur in the insert buffer at the first entry for this
3302
	index page */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3303
	btr_pcur_open_on_user_rec(
3304
		ibuf->index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
3305
		&pcur, &mtr);
3306
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3307
	if (!btr_pcur_is_on_user_rec(&pcur)) {
3308
		ut_ad(btr_pcur_is_after_last_in_tree(&pcur, &mtr));
3309
3310
		goto reset_bit;
3311
	}
3312
3313
	for (;;) {
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3314
		rec_t*	rec;
3315
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3316
		ut_ad(btr_pcur_is_on_user_rec(&pcur));
3317
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3318
		rec = btr_pcur_get_rec(&pcur);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3319
3320
		/* Check if the entry is for this index page */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3321
		if (ibuf_rec_get_page_no(rec) != page_no
3322
		    || ibuf_rec_get_space(rec) != space) {
3323
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3324
			if (block) {
3325
				page_header_reset_last_insert(
3326
					block->frame, page_zip, &mtr);
3327
			}
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3328
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3329
			goto reset_bit;
3330
		}
3331
3332
		if (UNIV_UNLIKELY(corruption_noticed)) {
3333
			fputs("InnoDB: Discarding record\n ", stderr);
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3334
			rec_print_old(stderr, rec);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3335
			fputs("\nInnoDB: from the insert buffer!\n\n", stderr);
3336
		} else if (block) {
3337
			/* Now we have at pcur a record which should be
3338
			inserted to the index page; NOTE that the call below
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3339
			copies pointers to fields in rec, and we must
3340
			keep the latch to the rec page until the
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3341
			insertion is finished! */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3342
			dtuple_t*	entry;
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3343
			trx_id_t	max_trx_id;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3344
			dict_index_t*	dummy_index;
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3345
3346
			max_trx_id = page_get_max_trx_id(page_align(rec));
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3347
			page_update_max_trx_id(block, page_zip, max_trx_id,
3348
					       &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3349
3350
			entry = ibuf_build_entry_from_ibuf_rec(
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3351
				rec, heap, &dummy_index);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3352
#ifdef UNIV_IBUF_DEBUG
3353
			volume += rec_get_converted_size(dummy_index, entry, 0)
3354
				+ page_dir_calc_reserved_space(1);
3355
			ut_a(volume <= 4 * UNIV_PAGE_SIZE
3356
			     / IBUF_PAGE_SIZE_PER_FREE_SPACE);
3357
#endif
3358
			ibuf_insert_to_index_page(entry, block,
3359
						  dummy_index, &mtr);
3360
			ibuf_dummy_index_free(dummy_index);
3361
		}
3362
3363
		n_inserts++;
3364
3365
		/* Delete the record from ibuf */
3366
		if (ibuf_delete_rec(space, page_no, &pcur, search_tuple,
3367
				    &mtr)) {
3368
			/* Deletion was pessimistic and mtr was committed:
3369
			we start from the beginning again */
3370
3371
			goto loop;
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3372
		} else if (btr_pcur_is_after_last_on_page(&pcur)) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3373
			mtr_commit(&mtr);
3374
			btr_pcur_close(&pcur);
3375
3376
			goto loop;
3377
		}
3378
	}
3379
3380
reset_bit:
3381
#ifdef UNIV_IBUF_COUNT_DEBUG
3382
	if (ibuf_count_get(space, page_no) > 0) {
3383
		/* btr_print_tree(ibuf_data->index->tree, 100);
3384
		ibuf_print(); */
3385
	}
3386
#endif
3387
	if (UNIV_LIKELY(update_ibuf_bitmap)) {
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3388
		page_t*	bitmap_page;
3389
3390
		bitmap_page = ibuf_bitmap_get_map_page(
3391
			space, page_no, zip_size, &mtr);
3392
3393
		ibuf_bitmap_page_set_bits(
3394
			bitmap_page, page_no, zip_size,
3395
			IBUF_BITMAP_BUFFERED, FALSE, &mtr);
3396
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3397
		if (block) {
3398
			ulint old_bits = ibuf_bitmap_page_get_bits(
3399
				bitmap_page, page_no, zip_size,
3400
				IBUF_BITMAP_FREE, &mtr);
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3401
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3402
			ulint new_bits = ibuf_index_page_calc_free(
3403
				zip_size, block);
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3404
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3405
			if (old_bits != new_bits) {
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3406
				ibuf_bitmap_page_set_bits(
3407
					bitmap_page, page_no, zip_size,
3408
					IBUF_BITMAP_FREE, new_bits, &mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3409
			}
3410
		}
3411
	}
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3412
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3413
	mtr_commit(&mtr);
3414
	btr_pcur_close(&pcur);
3415
	mem_heap_free(heap);
3416
3417
	/* Protect our statistics keeping from race conditions */
3418
	mutex_enter(&ibuf_mutex);
3419
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3420
	ibuf->n_merges++;
3421
	ibuf->n_merged_recs += n_inserts;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3422
3423
	mutex_exit(&ibuf_mutex);
3424
3425
	if (update_ibuf_bitmap && !tablespace_being_deleted) {
3426
3427
		fil_decr_pending_ibuf_merges(space);
3428
	}
3429
3430
	ibuf_exit();
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3431
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3432
#ifdef UNIV_IBUF_COUNT_DEBUG
3433
	ut_a(ibuf_count_get(space, page_no) == 0);
3434
#endif
3435
}
3436
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3437
/*********************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3438
Deletes all entries in the insert buffer for a given space id. This is used
3439
in DISCARD TABLESPACE and IMPORT TABLESPACE.
3440
NOTE: this does not update the page free bitmaps in the space. The space will
3441
become CORRUPT when you call this function! */
3442
UNIV_INTERN
3443
void
3444
ibuf_delete_for_discarded_space(
3445
/*============================*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3446
	ulint	space)	/*!< in: space id */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3447
{
3448
	mem_heap_t*	heap;
3449
	btr_pcur_t	pcur;
3450
	dtuple_t*	search_tuple;
3451
	rec_t*		ibuf_rec;
3452
	ulint		page_no;
3453
	ibool		closed;
3454
	ulint		n_inserts;
3455
	mtr_t		mtr;
3456
3457
	heap = mem_heap_create(512);
3458
3459
	/* Use page number 0 to build the search tuple so that we get the
3460
	cursor positioned at the first entry for this space id */
3461
3462
	search_tuple = ibuf_new_search_tuple_build(space, 0, heap);
3463
3464
	n_inserts = 0;
3465
loop:
3466
	ibuf_enter();
3467
3468
	mtr_start(&mtr);
3469
3470
	/* Position pcur in the insert buffer at the first entry for the
3471
	space */
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3472
	btr_pcur_open_on_user_rec(
3473
		ibuf->index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
3474
		&pcur, &mtr);
3475
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3476
	if (!btr_pcur_is_on_user_rec(&pcur)) {
3477
		ut_ad(btr_pcur_is_after_last_in_tree(&pcur, &mtr));
3478
3479
		goto leave_loop;
3480
	}
3481
3482
	for (;;) {
3483
		ut_ad(btr_pcur_is_on_user_rec(&pcur));
3484
3485
		ibuf_rec = btr_pcur_get_rec(&pcur);
3486
3487
		/* Check if the entry is for this space */
3488
		if (ibuf_rec_get_space(ibuf_rec) != space) {
3489
3490
			goto leave_loop;
3491
		}
3492
3493
		page_no = ibuf_rec_get_page_no(ibuf_rec);
3494
3495
		n_inserts++;
3496
3497
		/* Delete the record from ibuf */
3498
		closed = ibuf_delete_rec(space, page_no, &pcur, search_tuple,
3499
					 &mtr);
3500
		if (closed) {
3501
			/* Deletion was pessimistic and mtr was committed:
3502
			we start from the beginning again */
3503
3504
			ibuf_exit();
3505
3506
			goto loop;
3507
		}
3508
3509
		if (btr_pcur_is_after_last_on_page(&pcur)) {
3510
			mtr_commit(&mtr);
3511
			btr_pcur_close(&pcur);
3512
3513
			ibuf_exit();
3514
3515
			goto loop;
3516
		}
3517
	}
3518
3519
leave_loop:
3520
	mtr_commit(&mtr);
3521
	btr_pcur_close(&pcur);
3522
3523
	/* Protect our statistics keeping from race conditions */
3524
	mutex_enter(&ibuf_mutex);
3525
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3526
	ibuf->n_merges++;
3527
	ibuf->n_merged_recs += n_inserts;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3528
3529
	mutex_exit(&ibuf_mutex);
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3530
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3531
	ibuf_exit();
3532
3533
	mem_heap_free(heap);
3534
}
3535
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3536
/******************************************************************//**
3537
Looks if the insert buffer is empty.
3538
@return	TRUE if empty */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3539
UNIV_INTERN
3540
ibool
3541
ibuf_is_empty(void)
3542
/*===============*/
3543
{
3544
	ibool		is_empty;
3545
	const page_t*	root;
3546
	mtr_t		mtr;
3547
3548
	ibuf_enter();
3549
3550
	mutex_enter(&ibuf_mutex);
3551
3552
	mtr_start(&mtr);
3553
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3554
	root = ibuf_tree_root_get(&mtr);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3555
3556
	if (page_get_n_recs(root) == 0) {
3557
3558
		is_empty = TRUE;
3559
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3560
		if (ibuf->empty == FALSE) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3561
			fprintf(stderr,
3562
				"InnoDB: Warning: insert buffer tree is empty"
3563
				" but the data struct does not\n"
3564
				"InnoDB: know it. This condition is legal"
3565
				" if the master thread has not yet\n"
3566
				"InnoDB: run to completion.\n");
3567
		}
3568
	} else {
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3569
		ut_a(ibuf->empty == FALSE);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3570
3571
		is_empty = FALSE;
3572
	}
3573
3574
	mtr_commit(&mtr);
3575
3576
	mutex_exit(&ibuf_mutex);
3577
3578
	ibuf_exit();
3579
3580
	return(is_empty);
3581
}
3582
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3583
/******************************************************************//**
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3584
Prints info of ibuf. */
3585
UNIV_INTERN
3586
void
3587
ibuf_print(
3588
/*=======*/
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3589
	FILE*	file)	/*!< in: file where to print */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3590
{
3591
#ifdef UNIV_IBUF_COUNT_DEBUG
3592
	ulint		i;
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3593
	ulint		j;
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3594
#endif
3595
3596
	mutex_enter(&ibuf_mutex);
3597
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3598
	fprintf(file,
3599
		"Ibuf: size %lu, free list len %lu, seg size %lu,\n"
3600
		"%lu inserts, %lu merged recs, %lu merges\n",
3601
		(ulong) ibuf->size,
3602
		(ulong) ibuf->free_list_len,
3603
		(ulong) ibuf->seg_size,
3604
		(ulong) ibuf->n_inserts,
3605
		(ulong) ibuf->n_merged_recs,
3606
		(ulong) ibuf->n_merges);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3607
#ifdef UNIV_IBUF_COUNT_DEBUG
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3608
	for (i = 0; i < IBUF_COUNT_N_SPACES; i++) {
3609
		for (j = 0; j < IBUF_COUNT_N_PAGES; j++) {
3610
			ulint	count = ibuf_count_get(i, j);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3611
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3612
			if (count > 0) {
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3613
				fprintf(stderr,
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3614
					"Ibuf count for space/page %lu/%lu"
3615
					" is %lu\n",
3616
					(ulong) i, (ulong) j, (ulong) count);
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3617
			}
3618
		}
3619
	}
641.2.2 by Monty Taylor
InnoDB Plugin 1.0.3
3620
#endif /* UNIV_IBUF_COUNT_DEBUG */
641.1.2 by Monty Taylor
Imported 1.0.1 with clean - with no changes.
3621
3622
	mutex_exit(&ibuf_mutex);
3623
}
641.2.3 by Monty Taylor
InnoDB Plugin 1.0.4
3624
#endif /* !UNIV_HOTBACKUP */