From ffc0bc3eaf9ea45341462ebf16f8b70f2e2b74ea Mon Sep 17 00:00:00 2001
From: marko <Unknown>
Date: Thu, 18 Jan 2007 14:02:56 +0000
Subject: [PATCH] branches/zip: Free buffer blocks that are no longer needed
 for BLOB storage.

btr_blob_free(): New function to commit a mini-transaction and to free
an uncompressed BLOB block, or the entire block.

btr_store_big_rec_extern_fields(): Replace the existing code with
btr_blob_free().  The old code may have contained a race condition.

btr_free_externally_stored_field(): Completely free the buffer blocks
allocated for the freed BLOB.
---
 btr/btr0cur.c | 57 ++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 47 insertions(+), 10 deletions(-)

diff --git a/btr/btr0cur.c b/btr/btr0cur.c
index 1235fb8d04..a10255d717 100644
--- a/btr/btr0cur.c
+++ b/btr/btr0cur.c
@@ -3581,6 +3581,48 @@ btr_blob_get_next_page_no(
 	return(mach_read_from_4(blob_header + BTR_BLOB_HDR_NEXT_PAGE_NO));
 }
 
+/***********************************************************************
+Deallocate a buffer block that was reserved for a BLOB part. */
+static
+void
+btr_blob_free(
+/*==========*/
+	buf_block_t*	block,	/* in: buffer block */
+	ibool		all,	/* in: TRUE=remove also the compressed page
+				if there is one */
+	mtr_t*		mtr)	/* in: mini-transaction to commit */
+{
+	ulint	space	= buf_block_get_space(block);
+	ulint	page_no	= buf_block_get_page_no(block);
+
+	ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
+
+	mtr_commit(mtr);
+
+	mutex_enter(&buf_pool->mutex);
+	mutex_enter(&block->mutex);
+
+	/* Only free the block if it is still allocated to
+	the same file page. */
+
+	if (buf_block_get_state(block)
+	    == BUF_BLOCK_FILE_PAGE
+	    && buf_block_get_space(block) == space
+	    && buf_block_get_page_no(block) == page_no) {
+
+		if (!buf_LRU_free_block(&block->page, all)
+		    && all && block->page.zip.data) {
+			/* Attempt to deallocate the uncompressed page
+			if the whole block cannot be deallocted. */
+
+			buf_LRU_free_block(&block->page, FALSE);
+		}
+	}
+
+	mutex_exit(&buf_pool->mutex);
+	mutex_exit(&block->mutex);
+}
+
 /***********************************************************************
 Stores the fields in big_rec_vec to the tablespace and puts pointers to
 them in rec.  The extern flags in rec will have to be set beforehand.
@@ -3838,15 +3880,9 @@ btr_store_big_rec_extern_fields(
 next_zip_page:
 				prev_page_no = page_no;
 
-				mtr_commit(&mtr);
-
-				/* Release the uncompressed page frame
-				to save memory. */
-				mutex_enter(&buf_pool->mutex);
-				mutex_enter(&block->mutex);
-				buf_LRU_free_block(&block->page, FALSE);
-				mutex_exit(&buf_pool->mutex);
-				mutex_exit(&block->mutex);
+				/* Commit mtr and release the
+				uncompressed page frame to save memory. */
+				btr_blob_free(block, FALSE, &mtr);
 
 				if (err == Z_STREAM_END) {
 					break;
@@ -4100,7 +4136,8 @@ btr_free_externally_stored_field(
 			}
 		}
 
-		mtr_commit(&mtr);
+		/* Commit mtr and release the BLOB block to save memory. */
+		btr_blob_free(ext_block, TRUE, &mtr);
 	}
 }
 
-- 
2.30.9