List:Commits« Previous MessageNext Message »
From:marko.makela Date:May 24 2012 11:14am
Subject:bzr push into mysql-trunk-wl6255 branch (marko.makela:3861 to 3862)
View as plain text  
 3862 Marko Mäkelä	2012-05-24
      Fix errors in the rec_get_offsets() elimination.
      
      btr_root_raise_and_insert(), btr_page_split_and_insert(),
      btr_cur_pessimistic_insert(): Note that the memory heap for offsets
      can be emptied.
      
      btr_cur_pessimistic_update(), row_ins_sec_index_entry_by_modify(),
      row_ins_sec_index_entry_low(), row_log_apply_op_low(),
      row_log_apply_op(), row_undo_mod_clust_low(): Add offsets_heap for
      allocating offsets only. Note that it can be emptied.

    modified:
      storage/innobase/btr/btr0cur.cc
      storage/innobase/ibuf/ibuf0ibuf.cc
      storage/innobase/include/btr0btr.h
      storage/innobase/include/btr0cur.h
      storage/innobase/row/row0ins.cc
      storage/innobase/row/row0log.cc
      storage/innobase/row/row0umod.cc
      storage/innobase/row/row0upd.cc
 3861 Marko Mäkelä	2012-05-24
      Fix a bug in rec_get_offsets() elimination.
      
      btr_cur_pessimistic_update(): Allocate new_entry from a separate heap,
      because the heap for offsets can be emptied.

    modified:
      storage/innobase/btr/btr0cur.cc
=== modified file 'storage/innobase/btr/btr0cur.cc'
--- a/storage/innobase/btr/btr0cur.cc	revid:marko.makela@stripped4095608-1sdgx11fliddh4va
+++ b/storage/innobase/btr/btr0cur.cc	revid:marko.makela@strippedsb9upilai2
@@ -1464,7 +1464,8 @@ btr_cur_pessimistic_insert(
 	btr_cur_t*	cursor,	/*!< in: cursor after which to insert;
 				cursor stays valid */
 	ulint**		offsets,/*!< out: offsets on *rec */
-	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap, or NULL */
+	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap
+				that can be emptied, or NULL */
 	dtuple_t*	entry,	/*!< in/out: entry to insert */
 	rec_t**		rec,	/*!< out: pointer to inserted record if
 				succeed */
@@ -2230,7 +2231,12 @@ btr_cur_pessimistic_update(
 				cursor may become invalid if *big_rec == NULL
 				|| !(flags & BTR_KEEP_POS_FLAG) */
 	ulint**		offsets,/*!< out: offsets on cursor->page_cur.rec */
-	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap, or NULL */
+	mem_heap_t**	offsets_heap,
+				/*!< in/out: pointer to memory heap
+				that can be emptied, or NULL */
+	mem_heap_t*	entry_heap,
+				/*!< in/out: memory heap for allocating
+				big_rec and the index tuple */
 	big_rec_t**	big_rec,/*!< out: big rec vector whose fields have to
 				be stored externally by the caller, or NULL */
 	const upd_t*	update,	/*!< in: update vector; this is allowed also
@@ -2283,7 +2289,7 @@ btr_cur_pessimistic_update(
 			       | BTR_CREATE_FLAG | BTR_KEEP_SYS_FLAG));
 
 	optim_err = btr_cur_optimistic_update(
-		flags, cursor, offsets, heap, update,
+		flags, cursor, offsets, offsets_heap, update,
 		cmpl_info, thr, trx_id, mtr);
 
 	switch (optim_err) {
@@ -2326,13 +2332,10 @@ btr_cur_pessimistic_update(
 	}
 
 	*offsets = rec_get_offsets(
-		rec, index, *offsets, ULINT_UNDEFINED, heap);
+		rec, index, *offsets, ULINT_UNDEFINED, offsets_heap);
 
-	mem_heap_t*	new_entry_heap = mem_heap_create(
-		rec_offs_size(*offsets)
-		+ DTUPLE_EST_ALLOC(rec_offs_n_fields(*offsets)));
 	dtuple_t*	new_entry = row_rec_to_index_entry(
-		ROW_COPY_DATA, rec, index, *offsets, &n_ext, new_entry_heap);
+		ROW_COPY_DATA, rec, index, *offsets, &n_ext, entry_heap);
 
 	/* The page containing the clustered index record
 	corresponding to new_entry is latched in mtr.  If the
@@ -2341,7 +2344,7 @@ btr_cur_pessimistic_update(
 	purge would also have removed the clustered index record
 	itself.  Thus the following call is safe. */
 	row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
-						     FALSE, *heap);
+						     FALSE, entry_heap);
 	if (!(flags & BTR_KEEP_SYS_FLAG)) {
 		row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
 					      roll_ptr);
@@ -2370,7 +2373,7 @@ btr_cur_pessimistic_update(
 
 	ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
 	ut_ad(rec_offs_validate(rec, index, *offsets));
-	n_ext += btr_push_update_extern_fields(new_entry, update, *heap);
+	n_ext += btr_push_update_extern_fields(new_entry, update, entry_heap);
 
 	if (page_zip) {
 		ut_ad(page_is_comp(page));
@@ -2421,7 +2424,7 @@ make_external:
 	page_cur_move_to_prev(page_cursor);
 
 	rec = btr_cur_insert_if_possible(cursor, new_entry,
-					 offsets, heap, n_ext, mtr);
+					 offsets, offsets_heap, n_ext, mtr);
 
 	if (rec) {
 		page_cursor->rec = rec;
@@ -2485,7 +2488,7 @@ make_external:
 	err = btr_cur_pessimistic_insert(BTR_NO_UNDO_LOG_FLAG
 					 | BTR_NO_LOCKING_FLAG
 					 | BTR_KEEP_SYS_FLAG,
-					 cursor, offsets, heap,
+					 cursor, offsets, offsets_heap,
 					 new_entry, &rec,
 					 &dummy_big_rec, n_ext, NULL, mtr);
 	ut_a(rec);
@@ -2536,7 +2539,6 @@ make_external:
 	}
 
 return_after_reservations:
-	mem_heap_free(new_entry_heap);
 #ifdef UNIV_ZIP_DEBUG
 	ut_a(!page_zip || page_zip_validate(page_zip, page));
 #endif /* UNIV_ZIP_DEBUG */

=== modified file 'storage/innobase/ibuf/ibuf0ibuf.cc'
--- a/storage/innobase/ibuf/ibuf0ibuf.cc	revid:marko.makela@oracle.com-20120524095608-1sdgx11fliddh4va
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc	revid:marko.makela@stripped20120524111223-1l0272sb9upilai2
@@ -3238,6 +3238,7 @@ ibuf_insert_low(
 	btr_pcur_t	pcur;
 	btr_cur_t*	cursor;
 	dtuple_t*	ibuf_entry;
+	mem_heap_t*	offsets_heap	= NULL;
 	mem_heap_t*	heap;
 	ulint*		offsets		= NULL;
 	ulint		buffered;
@@ -3459,7 +3460,7 @@ fail_exit:
 	if (mode == BTR_MODIFY_PREV) {
 		err = btr_cur_optimistic_insert(
 			BTR_NO_LOCKING_FLAG,
-			cursor, &offsets, &heap,
+			cursor, &offsets, &offsets_heap,
 			ibuf_entry, &ins_rec,
 			&dummy_big_rec, 0, thr, &mtr);
 		block = btr_cur_get_block(cursor);
@@ -3486,11 +3487,11 @@ fail_exit:
 
 		root = ibuf_tree_root_get(&mtr);
 
-		err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG
-						 | BTR_NO_UNDO_LOG_FLAG,
-						 cursor, &offsets, &heap,
-						 ibuf_entry, &ins_rec,
-						 &dummy_big_rec, 0, thr, &mtr);
+		err = btr_cur_pessimistic_insert(
+			BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG,
+			cursor, &offsets, &offsets_heap,
+			ibuf_entry, &ins_rec,
+			&dummy_big_rec, 0, thr, &mtr);
 		mutex_exit(&ibuf_pessimistic_insert_mutex);
 		ibuf_size_update(root, &mtr);
 		mutex_exit(&ibuf_mutex);
@@ -3500,6 +3501,10 @@ fail_exit:
 		ut_ad(buf_block_get_space(block) == IBUF_SPACE_ID);
 	}
 
+	if (offsets_heap) {
+		mem_heap_free(offsets_heap);
+	}
+
 	if (err == DB_SUCCESS && op != IBUF_OP_DELETE) {
 		/* Update the page max trx id field */
 		page_update_max_trx_id(block, NULL,

=== modified file 'storage/innobase/include/btr0btr.h'
--- a/storage/innobase/include/btr0btr.h	revid:marko.makela@stripped
+++ b/storage/innobase/include/btr0btr.h	revid:marko.makela@oracle.com-20120524111223-1l0272sb9upilai2
@@ -428,7 +428,8 @@ btr_root_raise_and_insert(
 				the cursor is positioned on the predecessor
 				of the inserted record */
 	ulint**		offsets,/*!< out: offsets on inserted record */
-	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap, or NULL */
+	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap
+				that can be emptied, or NULL */
 	const dtuple_t*	tuple,	/*!< in: tuple to insert */
 	ulint		n_ext,	/*!< in: number of externally stored columns */
 	mtr_t*		mtr)	/*!< in: mtr */
@@ -492,7 +493,8 @@ btr_page_split_and_insert(
 				function returns, the cursor is positioned
 				on the predecessor of the inserted record */
 	ulint**		offsets,/*!< out: offsets on inserted record */
-	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap, or NULL */
+	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap
+				that can be emptied, or NULL */
 	const dtuple_t*	tuple,	/*!< in: tuple to insert */
 	ulint		n_ext,	/*!< in: number of externally stored columns */
 	mtr_t*		mtr)	/*!< in: mtr */

=== modified file 'storage/innobase/include/btr0cur.h'
--- a/storage/innobase/include/btr0cur.h	revid:marko.makela@stripped1fliddh4va
+++ b/storage/innobase/include/btr0cur.h	revid:marko.makela@stripped
@@ -247,7 +247,8 @@ btr_cur_pessimistic_insert(
 	btr_cur_t*	cursor,	/*!< in: cursor after which to insert;
 				cursor stays valid */
 	ulint**		offsets,/*!< out: offsets on *rec */
-	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap, or NULL */
+	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap
+				that can be emptied, or NULL */
 	dtuple_t*	entry,	/*!< in/out: entry to insert */
 	rec_t**		rec,	/*!< out: pointer to inserted record if
 				succeed */
@@ -339,7 +340,12 @@ btr_cur_pessimistic_update(
 				cursor may become invalid if *big_rec == NULL
 				|| !(flags & BTR_KEEP_POS_FLAG) */
 	ulint**		offsets,/*!< out: offsets on cursor->page_cur.rec */
-	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap, or NULL */
+	mem_heap_t**	offsets_heap,
+				/*!< in/out: pointer to memory heap
+				that can be emptied, or NULL */
+	mem_heap_t*	entry_heap,
+				/*!< in/out: memory heap for allocating
+				big_rec and the index tuple */
 	big_rec_t**	big_rec,/*!< out: big rec vector whose fields have to
 				be stored externally by the caller, or NULL */
 	const upd_t*	update,	/*!< in: update vector; this is allowed also
@@ -352,7 +358,7 @@ btr_cur_pessimistic_update(
 	trx_id_t	trx_id,	/*!< in: transaction id */
 	mtr_t*		mtr)	/*!< in: mtr; must be committed before
 				latching any further pages */
-	__attribute__((warn_unused_result, nonnull(2,3,4,5,6,10)));
+	__attribute__((warn_unused_result, nonnull(2,3,4,5,6,7,11)));
 /***********************************************************//**
 Marks a clustered index record deleted. Writes an undo log record to
 undo log on this delete marking. Writes in the trx id field the id

=== modified file 'storage/innobase/row/row0ins.cc'
--- a/storage/innobase/row/row0ins.cc	revid:marko.makela@oracle.com-20120524095608-1sdgx11fliddh4va
+++ b/storage/innobase/row/row0ins.cc	revid:marko.makela@stripped20524111223-1l0272sb9upilai2
@@ -235,6 +235,8 @@ row_ins_sec_index_entry_by_modify(
 				latch or also a tree latch */
 	btr_cur_t*	cursor,	/*!< in: B-tree cursor */
 	ulint**		offsets,/*!< in/out: offsets on cursor->page_cur.rec */
+	mem_heap_t*	offsets_heap,
+				/*!< in/out: memory heap that can be emptied */
 	mem_heap_t*	heap,	/*!< in/out: memory heap */
 	const dtuple_t*	entry,	/*!< in: index entry to insert */
 	que_thr_t*	thr,	/*!< in: query thread */
@@ -267,7 +269,7 @@ row_ins_sec_index_entry_by_modify(
 		/* TODO: pass only *offsets */
 		err = btr_cur_optimistic_update(
 			BTR_KEEP_SYS_FLAG, cursor,
-			offsets, &heap, update, 0, thr,
+			offsets, &offsets_heap, update, 0, thr,
 			thr_get_trx(thr)->id, mtr);
 		switch (err) {
 		case DB_OVERFLOW:
@@ -286,8 +288,9 @@ row_ins_sec_index_entry_by_modify(
 
 		err = btr_cur_pessimistic_update(
 			BTR_KEEP_SYS_FLAG, cursor,
-			offsets, &heap, &dummy_big_rec, update, 0, thr,
-			thr_get_trx(thr)->id, mtr);
+			offsets, &offsets_heap,
+			heap, &dummy_big_rec, update, 0,
+			thr, thr_get_trx(thr)->id, mtr);
 		ut_ad(!dummy_big_rec);
 	}
 
@@ -308,7 +311,10 @@ row_ins_clust_index_entry_by_modify(
 				latch or also a tree latch */
 	btr_cur_t*	cursor,	/*!< in: B-tree cursor */
 	ulint**		offsets,/*!< out: offsets on cursor->page_cur.rec */
-	mem_heap_t**	heap,	/*!< in/out: pointer to memory heap, or NULL */
+	mem_heap_t**	offsets_heap,
+				/*!< in/out: pointer to memory heap that can
+				be emptied, or NULL */
+	mem_heap_t*	heap,	/*!< in/out: memory heap */
 	big_rec_t**	big_rec,/*!< out: possible big rec vector of fields
 				which have to be stored externally by the
 				caller */
@@ -330,22 +336,18 @@ row_ins_clust_index_entry_by_modify(
 	ut_ad(rec_get_deleted_flag(rec,
 				   dict_table_is_comp(cursor->index->table)));
 
-	if (!*heap) {
-		*heap = mem_heap_create(1024);
-	}
-
 	/* Build an update vector containing all the fields to be modified;
 	NOTE that this vector may NOT contain system columns trx_id or
 	roll_ptr */
 
 	update = row_upd_build_difference_binary(cursor->index, entry, rec,
-						 thr_get_trx(thr), *heap);
+						 thr_get_trx(thr), heap);
 	if (mode == BTR_MODIFY_LEAF) {
 		/* Try optimistic updating of the record, keeping changes
 		within the page */
 
 		err = btr_cur_optimistic_update(
-			0, cursor, offsets, heap, update, 0, thr,
+			0, cursor, offsets, offsets_heap, update, 0, thr,
 			thr_get_trx(thr)->id, mtr);
 		switch (err) {
 		case DB_OVERFLOW:
@@ -364,8 +366,8 @@ row_ins_clust_index_entry_by_modify(
 		}
 		err = btr_cur_pessimistic_update(
 			BTR_KEEP_POS_FLAG,
-			cursor, offsets, heap, big_rec, update,
-			0, thr, thr_get_trx(thr)->id, mtr);
+			cursor, offsets, offsets_heap, heap,
+			big_rec, update, 0, thr, thr_get_trx(thr)->id, mtr);
 	}
 
 	return(err);
@@ -2142,7 +2144,7 @@ row_ins_clust_index_entry_low(
 	ulint		n_unique;
 	big_rec_t*	big_rec		= NULL;
 	mtr_t		mtr;
-	mem_heap_t*	heap		= NULL;
+	mem_heap_t*	offsets_heap	= NULL;
 
 	ut_ad(dict_index_is_clust(index));
 
@@ -2192,10 +2194,11 @@ err_exit:
 		/* There is already an index entry with a long enough common
 		prefix, we must convert the insert into a modify of an
 		existing record */
+		mem_heap_t*	entry_heap = mem_heap_create(1024);
 
 		err = row_ins_clust_index_entry_by_modify(
-			mode, &cursor, &offsets, &heap, &big_rec, entry,
-			thr, &mtr);
+			mode, &cursor, &offsets, &offsets_heap,
+			entry_heap, &big_rec, entry, thr, &mtr);
 
 		if (big_rec) {
 			ut_a(err == DB_SUCCESS);
@@ -2257,13 +2260,14 @@ err_exit:
 		}
 
 		mtr_commit(&mtr);
+		mem_heap_free(entry_heap);
 	} else {
 		rec_t*	insert_rec;
 
 		if (mode != BTR_MODIFY_TREE) {
 			ut_ad(mode == BTR_MODIFY_LEAF);
 			err = btr_cur_optimistic_insert(
-				0, &cursor, &offsets, &heap,
+				0, &cursor, &offsets, &offsets_heap,
 				entry, &insert_rec, &big_rec,
 				n_ext, thr, &mtr);
 		} else {
@@ -2273,7 +2277,7 @@ err_exit:
 				goto err_exit;
 			}
 			err = btr_cur_pessimistic_insert(
-				0, &cursor, &offsets, &heap,
+				0, &cursor, &offsets, &offsets_heap,
 				entry, &insert_rec, &big_rec,
 				n_ext, thr, &mtr);
 		}
@@ -2286,15 +2290,15 @@ err_exit:
 				log_make_checkpoint_at(
 					IB_ULONGLONG_MAX, TRUE););
 			err = row_ins_index_entry_big_rec(
-				entry, big_rec, offsets, &heap, index,
+				entry, big_rec, offsets, &offsets_heap, index,
 				thr_get_trx(thr)->mysql_thd,
 				__FILE__, __LINE__);
 			dtuple_convert_back_big_rec(index, entry, big_rec);
 		}
 	}
 
-	if (heap) {
-		mem_heap_free(heap);
+	if (offsets_heap) {
+		mem_heap_free(offsets_heap);
 	}
 
 	return(err);
@@ -2314,6 +2318,8 @@ row_ins_sec_index_entry_low(
 				depending on whether we wish optimistic or
 				pessimistic descent down the index tree */
 	dict_index_t*	index,	/*!< in: secondary index */
+	mem_heap_t*	offsets_heap,
+				/*!< in/out: memory heap that can be emptied */
 	mem_heap_t*	heap,	/*!< in/out: memory heap */
 	dtuple_t*	entry,	/*!< in/out: index entry to insert */
 	que_thr_t*	thr)	/*!< in: query thread */
@@ -2403,7 +2409,8 @@ row_ins_sec_index_entry_low(
 			ULINT_UNDEFINED, &heap);
 
 		err = row_ins_sec_index_entry_by_modify(
-			mode, &cursor, &offsets, heap, entry, thr, &mtr);
+			mode, &cursor, &offsets,
+			offsets_heap, heap, entry, thr, &mtr);
 	} else {
 		rec_t*		insert_rec;
 		big_rec_t*	big_rec;
@@ -2537,6 +2544,7 @@ row_ins_sec_index_entry(
 	que_thr_t*	thr)	/*!< in: query thread */
 {
 	dberr_t		err;
+	mem_heap_t*	offsets_heap;
 	mem_heap_t*	heap;
 
 	if (UT_LIST_GET_FIRST(index->table->foreign_list)) {
@@ -2553,22 +2561,25 @@ row_ins_sec_index_entry(
 		return(DB_SUCCESS);
 	}
 
+	offsets_heap = mem_heap_create(1024);
 	heap = mem_heap_create(1024);
 
 	/* Try first optimistic descent to the B-tree */
 
-	err = row_ins_sec_index_entry_low(BTR_MODIFY_LEAF, index, heap,
-					  entry, thr);
+	err = row_ins_sec_index_entry_low(BTR_MODIFY_LEAF, index,
+					  offsets_heap, heap, entry, thr);
 	if (err == DB_FAIL) {
 		mem_heap_empty(heap);
 
 		/* Try then pessimistic descent to the B-tree */
 
 		err = row_ins_sec_index_entry_low(
-			BTR_MODIFY_TREE, index, heap, entry, thr);
+			BTR_MODIFY_TREE, index,
+			offsets_heap, heap, entry, thr);
 	}
 
 	mem_heap_free(heap);
+	mem_heap_free(offsets_heap);
 	return(err);
 }
 

=== modified file 'storage/innobase/row/row0log.cc'
--- a/storage/innobase/row/row0log.cc	revid:marko.makela@stripped
+++ b/storage/innobase/row/row0log.cc	revid:marko.makela@oracle.com-20120524111223-1l0272sb9upilai2
@@ -340,6 +340,8 @@ row_log_apply_op_low(
 	row_merge_dup_t*dup,		/*!< in/out: for reporting
 					duplicate key errors */
 	dberr_t*	error,		/*!< out: DB_SUCCESS or error code */
+	mem_heap_t*	offsets_heap,	/*!< in/out: memory heap for
+					allocating offsets; can be emptied */
 	mem_heap_t*	heap,		/*!< in/out: memory heap for
 					allocating data tuples */
 	ibool		has_index_lock, /*!< in: TRUE if holding index->lock
@@ -388,7 +390,7 @@ row_log_apply_op_low(
 		ut_ad(page_rec_is_user_rec(rec));
 
 		offsets = rec_get_offsets(rec, index, NULL,
-					  ULINT_UNDEFINED, &heap);
+					  ULINT_UNDEFINED, &offsets_heap);
 		update = row_upd_build_sec_rec_difference_binary(
 			rec, index, offsets, entry, heap);
 
@@ -494,7 +496,7 @@ update_the_rec:
 					| BTR_NO_LOCKING_FLAG
 					| BTR_CREATE_FLAG
 					| BTR_KEEP_SYS_FLAG,
-					&cursor, &offsets, &heap,
+					&cursor, &offsets, &offsets_heap,
 					update, 0, NULL, trx_id, &mtr);
 
 				if (*error != DB_FAIL) {
@@ -525,8 +527,9 @@ update_the_rec:
 				| BTR_NO_LOCKING_FLAG
 				| BTR_CREATE_FLAG
 				| BTR_KEEP_SYS_FLAG,
-				&cursor, &offsets, &heap, &big_rec,
-				update, 0, NULL, trx_id, &mtr);
+				&cursor, &offsets, &offsets_heap,
+				heap, &big_rec, update,
+				0, NULL, trx_id, &mtr);
 			ut_ad(!big_rec);
 			break;
 
@@ -569,7 +572,7 @@ insert_the_rec:
 					BTR_NO_UNDO_LOG_FLAG
 					| BTR_NO_LOCKING_FLAG
 					| BTR_CREATE_FLAG,
-					&cursor, &offsets, &heap,
+					&cursor, &offsets, &offsets_heap,
 					const_cast<dtuple_t*>(entry),
 					&rec, &big_rec,
 					0, NULL, &mtr);
@@ -596,7 +599,7 @@ insert_the_rec:
 				BTR_NO_UNDO_LOG_FLAG
 				| BTR_NO_LOCKING_FLAG
 				| BTR_CREATE_FLAG,
-				&cursor, &offsets, &heap,
+				&cursor, &offsets, &offsets_heap,
 				const_cast<dtuple_t*>(entry),
 				&rec, &big_rec,
 				0, NULL, &mtr);
@@ -614,6 +617,7 @@ insert_the_rec:
 func_exit:
 	mtr_commit(&mtr);
 	mem_heap_empty(heap);
+	mem_heap_empty(offsets_heap);
 }
 
 /******************************************************//**
@@ -628,6 +632,8 @@ row_log_apply_op(
 	row_merge_dup_t*dup,		/*!< in/out: for reporting
 					duplicate key errors */
 	dberr_t*	error,		/*!< out: DB_SUCCESS or error code */
+	mem_heap_t*	offsets_heap,	/*!< in/out: memory heap for
+					allocating offsets; can be emptied */
 	mem_heap_t*	heap,		/*!< in/out: memory heap for
 					allocating data tuples */
 	ibool		has_index_lock, /*!< in: TRUE if holding index->lock
@@ -742,8 +748,8 @@ corrupted:
 		putc('\n', stderr);
 	}
 #endif /* ROW_LOG_APPLY_PRINT */
-	row_log_apply_op_low(index, dup, error, heap, has_index_lock,
-			     op, trx_id, entry);
+	row_log_apply_op_low(index, dup, error, offsets_heap, heap,
+			     has_index_lock, op, trx_id, entry);
 	return(mrec);
 }
 
@@ -765,6 +771,7 @@ row_log_apply_ops(
 	const mrec_t*	next_mrec;
 	const mrec_t*	mrec_end= NULL; /* silence bogus warning */
 	const mrec_t*	next_mrec_end;
+	mem_heap_t*	offsets_heap;
 	mem_heap_t*	heap;
 	ulint*		offsets;
 	ibool		has_index_lock;
@@ -783,6 +790,7 @@ row_log_apply_ops(
 	offsets[0] = i;
 	offsets[1] = dict_index_get_n_fields(index);
 
+	offsets_heap = mem_heap_create(UNIV_PAGE_SIZE);
 	heap = mem_heap_create(UNIV_PAGE_SIZE);
 	has_index_lock = TRUE;
 
@@ -892,8 +900,8 @@ all_done:
 		memcpy((mrec_t*) mrec_end, next_mrec,
 		       (&index->online_log->head.buf)[1] - mrec_end);
 		mrec = row_log_apply_op(
-			index, dup, &error, heap, has_index_lock,
-			index->online_log->head.buf,
+			index, dup, &error, offsets_heap, heap,
+			has_index_lock, index->online_log->head.buf,
 			(&index->online_log->head.buf)[1], offsets);
 		if (error != DB_SUCCESS) {
 			goto func_exit;
@@ -980,8 +988,8 @@ all_done:
 		}
 
 		next_mrec = row_log_apply_op(
-			index, dup, &error, heap, has_index_lock,
-			mrec, mrec_end, offsets);
+			index, dup, &error, offsets_heap, heap,
+			has_index_lock, mrec, mrec_end, offsets);
 
 		if (error != DB_SUCCESS) {
 			goto func_exit;
@@ -1048,6 +1056,7 @@ func_exit:
 	}
 
 	mem_heap_free(heap);
+	mem_heap_free(offsets_heap);
 	ut_free(offsets);
 	return(error);
 }

=== modified file 'storage/innobase/row/row0umod.cc'
--- a/storage/innobase/row/row0umod.cc	revid:marko.makela@stripped
+++ b/storage/innobase/row/row0umod.cc	revid:marko.makela@stripped-20120524111223-1l0272sb9upilai2
@@ -107,6 +107,8 @@ row_undo_mod_clust_low(
 /*===================*/
 	undo_node_t*	node,	/*!< in: row undo node */
 	ulint**		offsets,/*!< out: rec_get_offsets() on the record */
+	mem_heap_t**	offsets_heap,
+				/*!< in/out: memory heap that can be emptied */
 	mem_heap_t*	heap,	/*!< in/out: memory heap */
 	que_thr_t*	thr,	/*!< in: query thread */
 	mtr_t*		mtr,	/*!< in: mtr; must be committed before
@@ -135,13 +137,12 @@ row_undo_mod_clust_low(
 	      == thr_get_trx(thr)->id);
 
 	if (mode == BTR_MODIFY_LEAF) {
-		err = btr_cur_optimistic_update(BTR_NO_LOCKING_FLAG
-						| BTR_NO_UNDO_LOG_FLAG
-						| BTR_KEEP_SYS_FLAG,
-						btr_cur,
-						offsets, &heap, node->update,
-						node->cmpl_info, thr,
-						thr_get_trx(thr)->id, mtr);
+		err = btr_cur_optimistic_update(
+			BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG
+			| BTR_KEEP_SYS_FLAG,
+			btr_cur, offsets, offsets_heap,
+			node->update, node->cmpl_info,
+			thr, thr_get_trx(thr)->id, mtr);
 	} else {
 		big_rec_t*	dummy_big_rec;
 
@@ -151,7 +152,8 @@ row_undo_mod_clust_low(
 			BTR_NO_LOCKING_FLAG
 			| BTR_NO_UNDO_LOG_FLAG
 			| BTR_KEEP_SYS_FLAG,
-			btr_cur, offsets, &heap, &dummy_big_rec, node->update,
+			btr_cur, offsets, offsets_heap, heap,
+			&dummy_big_rec, node->update,
 			node->cmpl_info, thr, thr_get_trx(thr)->id, mtr);
 
 		ut_a(!dummy_big_rec);
@@ -254,14 +256,15 @@ row_undo_mod_clust(
 
 	mtr_start(&mtr);
 
-	mem_heap_t*	heap	= mem_heap_create(1024);
-	ulint*		offsets	= NULL;
+	mem_heap_t*	heap		= mem_heap_create(1024);
+	mem_heap_t*	offsets_heap	= NULL;
+	ulint*		offsets		= NULL;
 
 	/* Try optimistic processing of the record, keeping changes within
 	the index page */
 
-	err = row_undo_mod_clust_low(node, &offsets, heap, thr, &mtr,
-				     BTR_MODIFY_LEAF);
+	err = row_undo_mod_clust_low(node, &offsets, &offsets_heap,
+				     heap, thr, &mtr, BTR_MODIFY_LEAF);
 
 	if (err != DB_SUCCESS) {
 		btr_pcur_commit_specify_mtr(pcur, &mtr);
@@ -271,8 +274,9 @@ row_undo_mod_clust(
 
 		mtr_start(&mtr);
 
-		err = row_undo_mod_clust_low(node, &offsets, heap, thr, &mtr,
-					     BTR_MODIFY_TREE);
+		err = row_undo_mod_clust_low(
+			node, &offsets, &offsets_heap, heap, thr, &mtr,
+			BTR_MODIFY_TREE);
 		ut_ad(err == DB_SUCCESS || err == DB_OUT_OF_FILE_SPACE);
 	}
 
@@ -320,6 +324,9 @@ row_undo_mod_clust(
 		}
 	}
 
+	if (offsets_heap) {
+		mem_heap_free(offsets_heap);
+	}
 	mem_heap_free(heap);
 	return(err);
 }
@@ -517,6 +524,7 @@ row_undo_mod_del_unmark_sec_and_undo_upd
 
 	switch (search_result) {
 		mem_heap_t*	heap;
+		mem_heap_t*	offsets_heap;
 		ulint*		offsets;
 	case ROW_BUFFERED:
 	case ROW_NOT_DELETED_REF:
@@ -548,11 +556,11 @@ row_undo_mod_del_unmark_sec_and_undo_upd
 		ut_a(err == DB_SUCCESS);
 		heap = mem_heap_create(
 			sizeof(upd_t)
-			+ REC_OFFS_HEADER_SIZE * sizeof(*offsets)
-			+ dtuple_get_n_fields(entry)
-			* (sizeof(upd_field_t) + sizeof *offsets));
-		offsets = rec_get_offsets(btr_cur_get_rec(btr_cur),
-					  index, NULL, ULINT_UNDEFINED, &heap);
+			+ dtuple_get_n_fields(entry) * sizeof(upd_field_t));
+		offsets_heap = NULL;
+		offsets = rec_get_offsets(
+			btr_cur_get_rec(btr_cur),
+			index, NULL, ULINT_UNDEFINED, &offsets_heap);
 		update = row_upd_build_sec_rec_difference_binary(
 			btr_cur_get_rec(btr_cur), index, offsets, entry, heap);
 		if (upd_get_n_fields(update) == 0) {
@@ -566,8 +574,8 @@ row_undo_mod_del_unmark_sec_and_undo_upd
 			/* TODO: pass offsets, not &offsets */
 			err = btr_cur_optimistic_update(
 				BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG,
-				btr_cur, &offsets, &heap, update, 0, thr,
-				thr_get_trx(thr)->id, &mtr);
+				btr_cur, &offsets, &offsets_heap,
+				update, 0, thr, thr_get_trx(thr)->id, &mtr);
 			switch (err) {
 			case DB_OVERFLOW:
 			case DB_UNDERFLOW:
@@ -580,12 +588,14 @@ row_undo_mod_del_unmark_sec_and_undo_upd
 			ut_a(mode == BTR_MODIFY_TREE);
 			err = btr_cur_pessimistic_update(
 				BTR_KEEP_SYS_FLAG | BTR_NO_LOCKING_FLAG,
-				btr_cur, &offsets, &heap, &dummy_big_rec,
+				btr_cur, &offsets, &offsets_heap,
+				heap, &dummy_big_rec,
 				update, 0, thr, thr_get_trx(thr)->id, &mtr);
 			ut_a(!dummy_big_rec);
 		}
 
 		mem_heap_free(heap);
+		mem_heap_free(offsets_heap);
 	}
 
 	btr_pcur_close(&pcur);

=== modified file 'storage/innobase/row/row0upd.cc'
--- a/storage/innobase/row/row0upd.cc	revid:marko.makela@strippedm-20120524095608-1sdgx11fliddh4va
+++ b/storage/innobase/row/row0upd.cc	revid:marko.makela@stripped23-1l0272sb9upilai2
@@ -2066,6 +2066,7 @@ row_upd_clust_rec(
 	que_thr_t*	thr,	/*!< in: query thread */
 	mtr_t*		mtr)	/*!< in: mtr; gets committed here */
 {
+	mem_heap_t*	offsets_heap;
 	mem_heap_t*	heap;
 	big_rec_t*	big_rec	= NULL;
 	btr_pcur_t*	pcur;
@@ -2083,7 +2084,7 @@ row_upd_clust_rec(
 	ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
 				    dict_table_is_comp(index->table)));
 
-	heap = mem_heap_create(1024);
+	offsets_heap = NULL;
 
 	/* Try optimistic updating of the record, keeping changes within
 	the page; we do not check locks because we assume the x-lock on the
@@ -2093,7 +2094,7 @@ row_upd_clust_rec(
 		/* TODO: reuse offsets from caller */
 		offsets = rec_get_offsets(
 			btr_cur_get_rec(btr_cur),
-			index, offsets, ULINT_UNDEFINED, &heap);
+			index, offsets, ULINT_UNDEFINED, &offsets_heap);
 
 		err = btr_cur_update_in_place(
 			BTR_NO_LOCKING_FLAG, btr_cur,
@@ -2102,7 +2103,7 @@ row_upd_clust_rec(
 	} else {
 		err = btr_cur_optimistic_update(
 			BTR_NO_LOCKING_FLAG, btr_cur,
-			&offsets, &heap, node->update,
+			&offsets, &offsets_heap, node->update,
 			node->cmpl_info, thr, thr_get_trx(thr)->id, mtr);
 	}
 
@@ -2134,9 +2135,12 @@ row_upd_clust_rec(
 	ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
 				    dict_table_is_comp(index->table)));
 
+	heap = mem_heap_create(1024);
+
 	err = btr_cur_pessimistic_update(
 		BTR_NO_LOCKING_FLAG | BTR_KEEP_POS_FLAG, btr_cur,
-		&offsets, &heap, &big_rec, node->update, node->cmpl_info,
+		&offsets, &offsets_heap, heap, &big_rec,
+		node->update, node->cmpl_info,
 		thr, thr_get_trx(thr)->id, mtr);
 	if (big_rec) {
 		ut_a(err == DB_SUCCESS);
@@ -2184,8 +2188,11 @@ row_upd_clust_rec(
 	}
 
 	mtr_commit(mtr);
-func_exit:
 	mem_heap_free(heap);
+func_exit:
+	if (offsets_heap) {
+		mem_heap_free(offsets_heap);
+	}
 
 	if (big_rec) {
 		dtuple_big_rec_free(big_rec);

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-wl6255 branch (marko.makela:3861 to 3862) marko.makela24 May