From 6613d537670676f6cb0ce6d1dca7f07f79844065 Mon Sep 17 00:00:00 2001
From: marko <>
Date: Wed, 16 May 2007 12:01:31 +0000
Subject: [PATCH] branches/zip: btr_cur_optimistic_insert(): Set the insert
 buffer free bits exactly.  Rename the local variable "ulint level" to "ibool
 leaf". Document that if the function returns DB_SUCCESS on a compressed page
 that is covered by the insert buffer, the mini-transaction must be committed
 before latching any further pages.  Verify that this is the case on all
 execution paths.

---
 btr/btr0cur.c     | 49 +++++++++++++++++++++++++++--------------------
 include/btr0cur.h |  6 +++++-
 2 files changed, 33 insertions(+), 22 deletions(-)

diff --git a/btr/btr0cur.c b/btr/btr0cur.c
index cbb12bebb4d..a5cffdb5009 100644
--- a/btr/btr0cur.c
+++ b/btr/btr0cur.c
@@ -1043,7 +1043,11 @@ btr_cur_optimistic_insert(
 	const ulint*	ext,	/* in: array of extern field numbers */
 	ulint		n_ext,	/* in: number of elements in vec */
 	que_thr_t*	thr,	/* in: query thread or NULL */
-	mtr_t*		mtr)	/* in: mtr */
+	mtr_t*		mtr)	/* in: mtr; if this function returns
+				DB_SUCCESS on a leaf page of a secondary
+				index in a compressed tablespace, the
+				mtr must be committed before latching
+				any further pages */
 {
 	big_rec_t*	big_rec_vec	= NULL;
 	dict_index_t*	index;
@@ -1051,8 +1055,9 @@ btr_cur_optimistic_insert(
 	buf_block_t*	block;
 	page_t*		page;
 	ulint		max_size;
+	ulint		max_size_zip	= 0;
 	rec_t*		dummy_rec;
-	ulint		level;
+	ibool		leaf;
 	ibool		reorg;
 	ibool		inherit;
 	ulint		zip_size;
@@ -1080,7 +1085,18 @@ btr_cur_optimistic_insert(
 
 	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
 	max_size = page_get_max_insert_size_after_reorganize(page, 1);
-	level = btr_page_get_level(page, mtr);
+	leaf = page_is_leaf(page);
+
+	/* If necessary for updating the insert buffer bitmap,
+	calculate the current maximum insert size on a compressed page. */
+	if (zip_size && UNIV_LIKELY(leaf) && !dict_index_is_clust(index)) {
+		lint	zip_max = page_zip_max_ins_size(
+			buf_block_get_page_zip(block), FALSE);
+
+		if (zip_max >= 0 && max_size > (ulint) zip_max) {
+			max_size_zip = (ulint) zip_max;
+		}
+	}
 
 	/* Calculate the record size when entry is converted to a record */
 	rec_size = rec_get_converted_size(index, entry, ext, n_ext);
@@ -1106,7 +1122,7 @@ btr_cur_optimistic_insert(
 
 	if (dict_index_is_clust(index)
 	    && (page_get_n_recs(page) >= 2)
-	    && UNIV_LIKELY(0 == level)
+	    && UNIV_LIKELY(leaf)
 	    && (dict_index_get_space_reserve() + rec_size > max_size)
 	    && (btr_page_get_split_rec_to_right(cursor, &dummy_rec)
 		|| btr_page_get_split_rec_to_left(cursor, &dummy_rec))) {
@@ -1196,7 +1212,7 @@ fail_err:
 	}
 
 #ifdef BTR_CUR_HASH_ADAPT
-	if (!reorg && (0 == level) && (cursor->flag == BTR_CUR_HASH)) {
+	if (!reorg && leaf && (cursor->flag == BTR_CUR_HASH)) {
 		btr_search_update_hash_node_on_insert(cursor);
 	} else {
 		btr_search_update_hash_on_insert(cursor);
@@ -1214,17 +1230,9 @@ fail_err:
 		buf_block_get_page_no(block), max_size,
 		rec_size + PAGE_DIR_SLOT_SIZE, index->type);
 #endif
-	if (!dict_index_is_clust(index) && UNIV_LIKELY(0 == level)) {
+	if (!dict_index_is_clust(index) && leaf) {
 		/* Update the free bits of the B-tree page in the
-		insert buffer bitmap.  This has to be done in a
-		separate mini-transaction that is committed before the
-		main mini-transaction.  Since insert buffer bitmap
-		pages have a lower rank than B-tree pages, we must not
-		access other pages in the same mini-transaction after
-		accessing an insert buffer bitmap page.  Because the
-		mini-transaction where this function is invoked may
-		access other pages, we must update the insert
-		buffer bitmap in a separate mini-transaction. */
+		insert buffer bitmap. */
 
 		/* The free bits in the insert buffer bitmap must
 		never exceed the free space on a page.  It is safe to
@@ -1237,13 +1245,12 @@ fail_err:
 		the free bits could momentarily be set too high. */
 
 		if (zip_size) {
-			/* Because the free bits may be incremented
-			and we cannot update the insert buffer bitmap
-			in the same mini-transaction, the only safe
-			thing we can do here is the pessimistic
-			approach: reset the free bits. */
-			ibuf_reset_free_bits(block);
+			/* Update the bits in the same mini-transaction. */
+			ibuf_update_free_bits_low(zip_size, block,
+						  max_size_zip, mtr);
 		} else {
+			/* Decrement the bits in a separate
+			mini-transaction. */
 			ibuf_update_free_bits_if_full(
 				block, max_size,
 				rec_size + PAGE_DIR_SLOT_SIZE);
diff --git a/include/btr0cur.h b/include/btr0cur.h
index af7ba19f076..fa8daa74e11 100644
--- a/include/btr0cur.h
+++ b/include/btr0cur.h
@@ -180,7 +180,11 @@ btr_cur_optimistic_insert(
 	const ulint*	ext,	/* in: array of extern field numbers */
 	ulint		n_ext,	/* in: number of elements in vec */
 	que_thr_t*	thr,	/* in: query thread or NULL */
-	mtr_t*		mtr);	/* in: mtr */
+	mtr_t*		mtr);	/* in: mtr; if this function returns
+				DB_SUCCESS on a leaf page of a secondary
+				index in a compressed tablespace, the
+				mtr must be committed before latching
+				any further pages */
 /*****************************************************************
 Performs an insert on a page of an index tree. It is assumed that mtr
 holds an x-latch on the tree and on the cursor page. If the insert is