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
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 
17 *****************************************************************************/
18 
19 /**************************************************//**
20 @file include/ibuf0ibuf.h
21 Insert buffer
22 
23 Created 7/19/1997 Heikki Tuuri
24 *******************************************************/
25 
26 #ifndef ibuf0ibuf_h
27 #define ibuf0ibuf_h
28 
29 #include "univ.i"
30 
31 #include "mtr0mtr.h"
32 #include "dict0mem.h"
33 #include "fsp0fsp.h"
34 
35 #ifndef UNIV_HOTBACKUP
36 # include "ibuf0types.h"
37 
38 /* Possible operations buffered in the insert/whatever buffer. See
39 ibuf_insert(). DO NOT CHANGE THE VALUES OF THESE, THEY ARE STORED ON DISK. */
40 typedef enum {
41 	IBUF_OP_INSERT = 0,
42 	IBUF_OP_DELETE_MARK = 1,
43 	IBUF_OP_DELETE = 2,
44 
45 	/* Number of different operation types. */
46 	IBUF_OP_COUNT = 3
47 } ibuf_op_t;
48 
49 /** Combinations of operations that can be buffered.  Because the enum
50 values are used for indexing innobase_change_buffering_values[], they
51 should start at 0 and there should not be any gaps. */
52 typedef enum {
53 	IBUF_USE_NONE = 0,
54 	IBUF_USE_INSERT,	/* insert */
55 	IBUF_USE_DELETE_MARK,	/* delete */
56 	IBUF_USE_INSERT_DELETE_MARK,	/* insert+delete */
57 	IBUF_USE_DELETE,	/* delete+purge */
58 	IBUF_USE_ALL,		/* insert+delete+purge */
59 
60 	IBUF_USE_COUNT		/* number of entries in ibuf_use_t */
61 } ibuf_use_t;
62 
63 /** Operations that can currently be buffered. */
64 extern ibuf_use_t	ibuf_use;
65 
66 /** The insert buffer control structure */
67 extern ibuf_t*		ibuf;
68 
69 /* The purpose of the insert buffer is to reduce random disk access.
70 When we wish to insert a record into a non-unique secondary index and
71 the B-tree leaf page where the record belongs to is not in the buffer
72 pool, we insert the record into the insert buffer B-tree, indexed by
73 (space_id, page_no).  When the page is eventually read into the buffer
74 pool, we look up the insert buffer B-tree for any modifications to the
75 page, and apply these upon the completion of the read operation.  This
76 is called the insert buffer merge. */
77 
78 /* The insert buffer merge must always succeed.  To guarantee this,
79 the insert buffer subsystem keeps track of the free space in pages for
80 which it can buffer operations.  Two bits per page in the insert
81 buffer bitmap indicate the available space in coarse increments.  The
82 free bits in the insert buffer bitmap must never exceed the free space
83 on a page.  It is safe to decrement or reset the bits in the bitmap in
84 a mini-transaction that is committed before the mini-transaction that
85 affects the free space.  It is unsafe to increment the bits in a
86 separately committed mini-transaction, because in crash recovery, the
87 free bits could momentarily be set too high. */
88 
89 /******************************************************************//**
90 Creates the insert buffer data structure at a database startup. */
91 UNIV_INTERN
92 void
93 ibuf_init_at_db_start(void);
94 /*=======================*/
95 /*********************************************************************//**
96 Reads the biggest tablespace id from the high end of the insert buffer
97 tree and updates the counter in fil_system. */
98 UNIV_INTERN
99 void
100 ibuf_update_max_tablespace_id(void);
101 /*===============================*/
102 /***************************************************************//**
103 Starts an insert buffer mini-transaction. */
104 UNIV_INLINE
105 void
106 ibuf_mtr_start(
107 /*===========*/
108 	mtr_t*	mtr)	/*!< out: mini-transaction */
109 	__attribute__((nonnull));
110 /***************************************************************//**
111 Commits an insert buffer mini-transaction. */
112 UNIV_INLINE
113 void
114 ibuf_mtr_commit(
115 /*============*/
116 	mtr_t*	mtr)	/*!< in/out: mini-transaction */
117 	__attribute__((nonnull));
118 /*********************************************************************//**
119 Initializes an ibuf bitmap page. */
120 UNIV_INTERN
121 void
122 ibuf_bitmap_page_init(
123 /*==================*/
124 	buf_block_t*	block,	/*!< in: bitmap page */
125 	mtr_t*		mtr);	/*!< in: mtr */
126 /************************************************************************//**
127 Resets the free bits of the page in the ibuf bitmap. This is done in a
128 separate mini-transaction, hence this operation does not restrict
129 further work to only ibuf bitmap operations, which would result if the
130 latch to the bitmap page were kept.  NOTE: The free bits in the insert
131 buffer bitmap must never exceed the free space on a page.  It is safe
132 to decrement or reset the bits in the bitmap in a mini-transaction
133 that is committed before the mini-transaction that affects the free
134 space. */
135 UNIV_INTERN
136 void
137 ibuf_reset_free_bits(
138 /*=================*/
139 	buf_block_t*	block);	/*!< in: index page; free bits are set to 0
140 				if the index is a non-clustered
141 				non-unique, and page level is 0 */
142 /************************************************************************//**
143 Updates the free bits of an uncompressed page in the ibuf bitmap if
144 there is not enough free on the page any more.  This is done in a
145 separate mini-transaction, hence this operation does not restrict
146 further work to only ibuf bitmap operations, which would result if the
147 latch to the bitmap page were kept.  NOTE: The free bits in the insert
148 buffer bitmap must never exceed the free space on a page.  It is
149 unsafe to increment the bits in a separately committed
150 mini-transaction, because in crash recovery, the free bits could
151 momentarily be set too high.  It is only safe to use this function for
152 decrementing the free bits.  Should more free space become available,
153 we must not update the free bits here, because that would break crash
154 recovery. */
155 UNIV_INLINE
156 void
157 ibuf_update_free_bits_if_full(
158 /*==========================*/
159 	buf_block_t*	block,	/*!< in: index page to which we have added new
160 				records; the free bits are updated if the
161 				index is non-clustered and non-unique and
162 				the page level is 0, and the page becomes
163 				fuller */
164 	ulint		max_ins_size,/*!< in: value of maximum insert size with
165 				reorganize before the latest operation
166 				performed to the page */
167 	ulint		increase);/*!< in: upper limit for the additional space
168 				used in the latest operation, if known, or
169 				ULINT_UNDEFINED */
170 /**********************************************************************//**
171 Updates the free bits for an uncompressed page to reflect the present
172 state.  Does this in the mtr given, which means that the latching
173 order rules virtually prevent any further operations for this OS
174 thread until mtr is committed.  NOTE: The free bits in the insert
175 buffer bitmap must never exceed the free space on a page.  It is safe
176 to set the free bits in the same mini-transaction that updated the
177 page. */
178 UNIV_INTERN
179 void
180 ibuf_update_free_bits_low(
181 /*======================*/
182 	const buf_block_t*	block,		/*!< in: index page */
183 	ulint			max_ins_size,	/*!< in: value of
184 						maximum insert size
185 						with reorganize before
186 						the latest operation
187 						performed to the page */
188 	mtr_t*			mtr);		/*!< in/out: mtr */
189 /**********************************************************************//**
190 Updates the free bits for a compressed page to reflect the present
191 state.  Does this in the mtr given, which means that the latching
192 order rules virtually prevent any further operations for this OS
193 thread until mtr is committed.  NOTE: The free bits in the insert
194 buffer bitmap must never exceed the free space on a page.  It is safe
195 to set the free bits in the same mini-transaction that updated the
196 page. */
197 UNIV_INTERN
198 void
199 ibuf_update_free_bits_zip(
200 /*======================*/
201 	buf_block_t*	block,	/*!< in/out: index page */
202 	mtr_t*		mtr);	/*!< in/out: mtr */
203 /**********************************************************************//**
204 Updates the free bits for the two pages to reflect the present state.
205 Does this in the mtr given, which means that the latching order rules
206 virtually prevent any further operations until mtr is committed.
207 NOTE: The free bits in the insert buffer bitmap must never exceed the
208 free space on a page.  It is safe to set the free bits in the same
209 mini-transaction that updated the pages. */
210 UNIV_INTERN
211 void
212 ibuf_update_free_bits_for_two_pages_low(
213 /*====================================*/
214 	ulint		zip_size,/*!< in: compressed page size in bytes;
215 				0 for uncompressed pages */
216 	buf_block_t*	block1,	/*!< in: index page */
217 	buf_block_t*	block2,	/*!< in: index page */
218 	mtr_t*		mtr);	/*!< in: mtr */
219 /**********************************************************************//**
220 A basic partial test if an insert to the insert buffer could be possible and
221 recommended. */
222 UNIV_INLINE
223 ibool
224 ibuf_should_try(
225 /*============*/
226 	dict_index_t*	index,			/*!< in: index where to insert */
227 	ulint		ignore_sec_unique);	/*!< in: if != 0, we should
228 						ignore UNIQUE constraint on
229 						a secondary index when we
230 						decide */
231 /******************************************************************//**
232 Returns TRUE if the current OS thread is performing an insert buffer
233 routine.
234 
235 For instance, a read-ahead of non-ibuf pages is forbidden by threads
236 that are executing an insert buffer routine.
237 @return TRUE if inside an insert buffer routine */
238 UNIV_INLINE
239 ibool
240 ibuf_inside(
241 /*========*/
242 	const mtr_t*	mtr)	/*!< in: mini-transaction */
243 	__attribute__((nonnull, pure));
244 /***********************************************************************//**
245 Checks if a page address is an ibuf bitmap page (level 3 page) address.
246 @return	TRUE if a bitmap page */
247 UNIV_INLINE
248 ibool
249 ibuf_bitmap_page(
250 /*=============*/
251 	ulint	zip_size,/*!< in: compressed page size in bytes;
252 			0 for uncompressed pages */
253 	ulint	page_no);/*!< in: page number */
254 /***********************************************************************//**
255 Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
256 Must not be called when recv_no_ibuf_operations==TRUE.
257 @return	TRUE if level 2 or level 3 page */
258 UNIV_INTERN
259 ibool
260 ibuf_page_low(
261 /*==========*/
262 	ulint		space,	/*!< in: space id */
263 	ulint		zip_size,/*!< in: compressed page size in bytes, or 0 */
264 	ulint		page_no,/*!< in: page number */
265 #ifdef UNIV_DEBUG
266 	ibool		x_latch,/*!< in: FALSE if relaxed check
267 				(avoid latching the bitmap page) */
268 #endif /* UNIV_DEBUG */
269 	const char*	file,	/*!< in: file name */
270 	ulint		line,	/*!< in: line where called */
271 	mtr_t*		mtr)	/*!< in: mtr which will contain an
272 				x-latch to the bitmap page if the page
273 				is not one of the fixed address ibuf
274 				pages, or NULL, in which case a new
275 				transaction is created. */
276 	__attribute__((warn_unused_result));
277 #ifdef UNIV_DEBUG
278 /** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of
279 pages.  Must not be called when recv_no_ibuf_operations==TRUE.
280 @param space	tablespace identifier
281 @param zip_size	compressed page size in bytes, or 0
282 @param page_no	page number
283 @param mtr	mini-transaction or NULL
284 @return TRUE if level 2 or level 3 page */
285 # define ibuf_page(space, zip_size, page_no, mtr)			\
286 	ibuf_page_low(space, zip_size, page_no, TRUE, __FILE__, __LINE__, mtr)
287 #else /* UVIV_DEBUG */
288 /** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of
289 pages.  Must not be called when recv_no_ibuf_operations==TRUE.
290 @param space	tablespace identifier
291 @param zip_size	compressed page size in bytes, or 0
292 @param page_no	page number
293 @param mtr	mini-transaction or NULL
294 @return TRUE if level 2 or level 3 page */
295 # define ibuf_page(space, zip_size, page_no, mtr)			\
296 	ibuf_page_low(space, zip_size, page_no, __FILE__, __LINE__, mtr)
297 #endif /* UVIV_DEBUG */
298 /***********************************************************************//**
299 Frees excess pages from the ibuf free list. This function is called when an OS
300 thread calls fsp services to allocate a new file segment, or a new page to a
301 file segment, and the thread did not own the fsp latch before this call. */
302 UNIV_INTERN
303 void
304 ibuf_free_excess_pages(void);
305 /*========================*/
306 /*********************************************************************//**
307 Buffer an operation in the insert/delete buffer, instead of doing it
308 directly to the disk page, if this is possible. Does not do it if the index
309 is clustered or unique.
310 @return	TRUE if success */
311 UNIV_INTERN
312 ibool
313 ibuf_insert(
314 /*========*/
315 	ibuf_op_t	op,	/*!< in: operation type */
316 	const dtuple_t*	entry,	/*!< in: index entry to insert */
317 	dict_index_t*	index,	/*!< in: index where to insert */
318 	ulint		space,	/*!< in: space id where to insert */
319 	ulint		zip_size,/*!< in: compressed page size in bytes, or 0 */
320 	ulint		page_no,/*!< in: page number where to insert */
321 	que_thr_t*	thr);	/*!< in: query thread */
322 /*********************************************************************//**
323 When an index page is read from a disk to the buffer pool, this function
324 applies any buffered operations to the page and deletes the entries from the
325 insert buffer. If the page is not read, but created in the buffer pool, this
326 function deletes its buffered entries from the insert buffer; there can
327 exist entries for such a page if the page belonged to an index which
328 subsequently was dropped. */
329 UNIV_INTERN
330 void
331 ibuf_merge_or_delete_for_page(
332 /*==========================*/
333 	buf_block_t*	block,	/*!< in: if page has been read from
334 				disk, pointer to the page x-latched,
335 				else NULL */
336 	ulint		space,	/*!< in: space id of the index page */
337 	ulint		page_no,/*!< in: page number of the index page */
338 	ulint		zip_size,/*!< in: compressed page size in bytes,
339 				or 0 */
340 	ibool		update_ibuf_bitmap);/*!< in: normally this is set
341 				to TRUE, but if we have deleted or are
342 				deleting the tablespace, then we
343 				naturally do not want to update a
344 				non-existent bitmap page */
345 /*********************************************************************//**
346 Deletes all entries in the insert buffer for a given space id. This is used
347 in DISCARD TABLESPACE and IMPORT TABLESPACE.
348 NOTE: this does not update the page free bitmaps in the space. The space will
349 become CORRUPT when you call this function! */
350 UNIV_INTERN
351 void
352 ibuf_delete_for_discarded_space(
353 /*============================*/
354 	ulint	space);	/*!< in: space id */
355 /*********************************************************************//**
356 Contracts insert buffer trees by reading pages to the buffer pool.
357 @return a lower limit for the combined size in bytes of entries which
358 will be merged from ibuf trees to the pages read, 0 if ibuf is
359 empty */
360 UNIV_INTERN
361 ulint
362 ibuf_contract(
363 /*==========*/
364 	ibool	sync);	/*!< in: TRUE if the caller wants to wait for the
365 			issued read with the highest tablespace address
366 			to complete */
367 /*********************************************************************//**
368 Contracts insert buffer trees by reading pages to the buffer pool.
369 @return a lower limit for the combined size in bytes of entries which
370 will be merged from ibuf trees to the pages read, 0 if ibuf is
371 empty */
372 UNIV_INTERN
373 ulint
374 ibuf_contract_for_n_pages(
375 /*======================*/
376 	ibool	sync,	/*!< in: TRUE if the caller wants to wait for the
377 			issued read with the highest tablespace address
378 			to complete */
379 	ulint	n_pages);/*!< in: try to read at least this many pages to
380 			the buffer pool and merge the ibuf contents to
381 			them */
382 #endif /* !UNIV_HOTBACKUP */
383 /*********************************************************************//**
384 Parses a redo log record of an ibuf bitmap page init.
385 @return	end of log record or NULL */
386 UNIV_INTERN
387 byte*
388 ibuf_parse_bitmap_init(
389 /*===================*/
390 	byte*		ptr,	/*!< in: buffer */
391 	byte*		end_ptr,/*!< in: buffer end */
392 	buf_block_t*	block,	/*!< in: block or NULL */
393 	mtr_t*		mtr);	/*!< in: mtr or NULL */
394 #ifndef UNIV_HOTBACKUP
395 #ifdef UNIV_IBUF_COUNT_DEBUG
396 /******************************************************************//**
397 Gets the ibuf count for a given page.
398 @return number of entries in the insert buffer currently buffered for
399 this page */
400 UNIV_INTERN
401 ulint
402 ibuf_count_get(
403 /*===========*/
404 	ulint	space,	/*!< in: space id */
405 	ulint	page_no);/*!< in: page number */
406 #endif
407 /******************************************************************//**
408 Looks if the insert buffer is empty.
409 @return	TRUE if empty */
410 UNIV_INTERN
411 ibool
412 ibuf_is_empty(void);
413 /*===============*/
414 /******************************************************************//**
415 Prints info of ibuf. */
416 UNIV_INTERN
417 void
418 ibuf_print(
419 /*=======*/
420 	FILE*	file);	/*!< in: file where to print */
421 /********************************************************************
422 Read the first two bytes from a record's fourth field (counter field in new
423 records; something else in older records).
424 @return	"counter" field, or ULINT_UNDEFINED if for some reason it can't be read */
425 UNIV_INTERN
426 ulint
427 ibuf_rec_get_counter(
428 /*=================*/
429 	const rec_t*	rec);	/*!< in: ibuf record */
430 /******************************************************************//**
431 Closes insert buffer and frees the data structures. */
432 UNIV_INTERN
433 void
434 ibuf_close(void);
435 /*============*/
436 
437 #define IBUF_HEADER_PAGE_NO	FSP_IBUF_HEADER_PAGE_NO
438 #define IBUF_TREE_ROOT_PAGE_NO	FSP_IBUF_TREE_ROOT_PAGE_NO
439 
440 #endif /* !UNIV_HOTBACKUP */
441 
442 /* The ibuf header page currently contains only the file segment header
443 for the file segment from which the pages for the ibuf tree are allocated */
444 #define IBUF_HEADER		PAGE_DATA
445 #define	IBUF_TREE_SEG_HEADER	0	/* fseg header for ibuf tree */
446 
447 /* The insert buffer tree itself is always located in space 0. */
448 #define IBUF_SPACE_ID		0
449 
450 #ifndef UNIV_NONINL
451 #include "ibuf0ibuf.ic"
452 #endif
453 
454 #endif
455