List:Commits« Previous MessageNext Message »
From:marko.makela Date:May 30 2012 12:57pm
Subject:bzr push into mysql-trunk-wl6255 branch (marko.makela:3907 to 3909) WL#6255
View as plain text  
 3909 Marko Mäkelä	2012-05-30
      WL#6255: Fix the online rebuild logging of ROW_FORMAT=REDUNDANT tables.
      
      Move some accessor function prototypes and #defines from rem0rec.ic
      to rem0rec.h.
      
      rec_2_is_field_extern(): Determine if a field is stored externally.
      
      row_log_table_low_redundant(): Like row_log_table_low(), but for
      ROW_FORMAT=REDUNDANT records. Convert the rec_t to a dtuple_t and
      then to the rebuild log format. Add some assertions.

    modified:
      storage/innobase/include/rem0rec.h
      storage/innobase/include/rem0rec.ic
      storage/innobase/row/row0log.cc
 3908 Marko Mäkelä	2012-05-30
      btr_page_split_and_insert(): Do not release the index tree X-latch
      when the table is being rebuilt online.

    modified:
      storage/innobase/btr/btr0btr.cc
 3907 Marko Mal change):
      
      row_log_table_low(): Common function for row_log_table_update()
      and row_log_table_insert().

    modified:
      storage/innobase/row/row0log.cc
=== modified file 'storage/innobase/btr/btr0btr.cc'
--- a/storage/innobase/btr/btr0btr.cc	revid:marko.makela@oracle.com-20120530112326-5edq0xc9linup4yt
+++ b/storage/innobase/btr/btr0btr.cc	revid:marko.makela@stripped20530125444-m89sg202qswa44h4
@@ -2598,6 +2598,8 @@ func_start:
 
 	ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(cursor->index),
 				MTR_MEMO_X_LOCK));
+	ut_ad(!dict_index_is_online_ddl(cursor->index)
+	      || dict_index_is_clust(cursor->index));
 #ifdef UNIV_SYNC_DEBUG
 	ut_ad(rw_lock_own(dict_index_get_lock(cursor->index), RW_LOCK_EX));
 #endif /* UNIV_SYNC_DEBUG */
@@ -2721,7 +2723,8 @@ insert_empty:
 						offsets, tuple, n_ext, heap);
 	}
 
-	if (insert_will_fit && page_is_leaf(page)) {
+	if (insert_will_fit && page_is_leaf(page)
+	    && !dict_index_is_online_ddl(cursor->index)) {
 
 		mtr_memo_release(mtr, dict_index_get_lock(cursor->index),
 				 MTR_MEMO_X_LOCK);

=== modified file 'storage/innobase/include/rem0rec.h'
--- a/storage/innobase/include/rem0rec.h	revid:marko.makela@stripped
+++ b/storage/innobase/include/rem0rec.h	revid:marko.makela@oracle.com-20120530125444-m89sg202qswa44h4
@@ -66,6 +66,15 @@ The status is stored in the low-order bi
 /* Length of a B-tree node pointer, in bytes */
 #define REC_NODE_PTR_SIZE	4
 
+/** SQL null flag in a 1-byte offset of ROW_FORMAT=REDUNDANT record s*/
+#define REC_1BYTE_SQL_NULL_MASK	0x80UL
+/** SQL null flag in a 2-byte offset of ROW_FORMAT=REDUNDANT record s*/
+#define REC_2BYTE_SQL_NULL_MASK	0x8000UL
+
+/** In a 2-byte offset of ROW_FORMAT=REDUNDANT records, the second most
+significant bit denotes that the tail of a field is stored off-page. */
+#define REC_2BYTE_EXTERN_MASK	0x4000UL
+
 #ifdef UNIV_DEBUG
 /* Length of the rec_get_offsets() header */
 # define REC_OFFS_HEADER_SIZE	4
@@ -353,6 +362,55 @@ rec_get_1byte_offs_flag(
 	__attribute__((nonnull, pure, warn_unused_result));
 
 /******************************************************//**
+The following function is used to set the 1-byte offsets flag. */
+UNIV_INLINE
+void
+rec_set_1byte_offs_flag(
+/*====================*/
+	rec_t*	rec,	/*!< in: physical record */
+	ibool	flag)	/*!< in: TRUE if 1byte form */
+	__attribute__((nonnull));
+
+/******************************************************//**
+Returns the offset of nth field end if the record is stored in the 1-byte
+offsets form. If the field is SQL null, the flag is ORed in the returned
+value.
+@return	offset of the start of the field, SQL null flag ORed */
+UNIV_INLINE
+ulint
+rec_1_get_field_end_info(
+/*=====================*/
+	const rec_t*	rec,	/*!< in: record */
+	ulint		n)	/*!< in: field index */
+	__attribute__((nonnull, pure, warn_unused_result));
+
+/******************************************************//**
+Returns the offset of nth field end if the record is stored in the 2-byte
+offsets form. If the field is SQL null, the flag is ORed in the returned
+value.
+@return offset of the start of the field, SQL null flag and extern
+storage flag ORed */
+UNIV_INLINE
+ulint
+rec_2_get_field_end_info(
+/*=====================*/
+	const rec_t*	rec,	/*!< in: record */
+	ulint		n)	/*!< in: field index */
+	__attribute__((nonnull, pure, warn_unused_result));
+
+/******************************************************//**
+Returns nonzero if the field is stored off-page.
+@retval 0 if the field is stored in-page
+@retval REC_2BYTE_EXTERN_MASK if the field is stored externally */
+UNIV_INLINE
+ulint
+rec_2_is_field_extern(
+/*==================*/
+	const rec_t*	rec,	/*!< in: record */
+	ulint		n)	/*!< in: field index */
+	__attribute__((nonnull, pure, warn_unused_result));
+
+/******************************************************//**
 Determine how many of the first n columns in a compact
 physical record are stored externally.
 @return	number of externally stored columns */

=== modified file 'storage/innobase/include/rem0rec.ic'
--- a/storage/innobase/include/rem0rec.ic	revid:marko.makela@stripped
+++ b/storage/innobase/include/rem0rec.ic	revid:marko.makela@oracle.com-20120530125444-m89sg202qswa44h4
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
 
 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
@@ -118,17 +118,6 @@ and the shift needed to obtain each bit-
 #define	REC_INFO_BITS_MASK	0xF0UL
 #define REC_INFO_BITS_SHIFT	0
 
-/* The following masks are used to filter the SQL null bit from
-one-byte and two-byte offsets */
-
-#define REC_1BYTE_SQL_NULL_MASK	0x80UL
-#define REC_2BYTE_SQL_NULL_MASK	0x8000UL
-
-/* In a 2-byte offset the second most significant bit denotes
-a field stored to another page: */
-
-#define REC_2BYTE_EXTERN_MASK	0x4000UL
-
 #if REC_OLD_SHORT_MASK << (8 * (REC_OLD_SHORT - 3)) \
 		^ REC_OLD_N_FIELDS_MASK << (8 * (REC_OLD_N_FIELDS - 4)) \
 		^ REC_HEAP_NO_MASK << (8 * (REC_OLD_HEAP_NO - 4)) \
@@ -883,6 +872,20 @@ rec_2_get_field_end_info(
 	return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2)));
 }
 
+/******************************************************//**
+Returns nonzero if the field is stored off-page.
+@retval 0 if the field is stored in-page
+@retval REC_2BYTE_EXTERN_MASK if the field is stored externally */
+UNIV_INLINE
+ulint
+rec_2_is_field_extern(
+/*==================*/
+	const rec_t*	rec,	/*!< in: record */
+	ulint		n)	/*!< in: field index */
+{
+	return(rec_2_get_field_end_info(rec, n) & REC_2BYTE_EXTERN_MASK);
+}
+
 /* Get the base address of offsets.  The extra_size is stored at
 this position, and following positions hold the end offsets of
 the fields. */

=== modified file 'storage/innobase/row/row0log.cc'
--- a/storage/innobase/row/row0log.cc	revid:marko.makela@strippedp4yt
+++ b/storage/innobase/row/row0log.cc	revid:marko.makela@stripped
@@ -503,6 +503,134 @@ row_log_table_delete(
 Logs an insert or update to a table that is being rebuilt. */
 static __attribute__((nonnull(1,2,3)))
 void
+row_log_table_low_redundant(
+/*========================*/
+	const rec_t*		rec,	/*!< in: clustered index leaf
+					page record in ROW_FORMAT=REDUNDANT,
+					page X-latched */
+	dict_index_t*		index,	/*!< in/out: clustered index, S-latched
+					or X-latched */
+	const ulint*		offsets,/*!< in: rec_get_offsets(rec,index) */
+	bool			insert,	/*!< in: true if insert,
+					false if update */
+	const dtuple_t*		old_pk,	/*!< in: old PRIMARY KEY value
+					(if !insert and a PRIMARY KEY
+					is being created) */
+	const dict_index_t*	new_index)
+					/*!< in: clustered index of the
+					new table, not latched */
+{
+	ulint		old_pk_size;
+	ulint		old_pk_extra_size;
+	ulint		size;
+	ulint		extra_size;
+	ulint		mrec_size;
+	ulint		avail_size;
+	mem_heap_t*	heap		= NULL;
+	dtuple_t*	tuple;
+
+	ut_ad(!page_is_comp(page_align(rec)));
+	ut_ad(dict_index_get_n_fields(index) == rec_get_n_fields_old(rec));
+
+	heap = mem_heap_create(DTUPLE_EST_ALLOC(index->n_fields));
+	tuple = dtuple_create(heap, index->n_fields);
+	dict_index_copy_types(tuple, index, index->n_fields);
+	dtuple_set_n_fields_cmp(tuple, dict_index_get_n_unique(index));
+
+	if (rec_get_1byte_offs_flag(rec)) {
+		for (ulint i = 0; i < index->n_fields; i++) {
+			dfield_t*	dfield;
+			ulint		len;
+			const void*	field;
+
+			dfield = dtuple_get_nth_field(tuple, i);
+			field = rec_get_nth_field_old(rec, i, &len);
+
+			dfield_set_data(dfield, field, len);
+		}
+	} else {
+		for (ulint i = 0; i < index->n_fields; i++) {
+			dfield_t*	dfield;
+			ulint		len;
+			const void*	field;
+
+			dfield = dtuple_get_nth_field(tuple, i);
+			field = rec_get_nth_field_old(rec, i, &len);
+
+			dfield_set_data(dfield, field, len);
+
+			if (rec_2_is_field_extern(rec, i)) {
+				dfield_set_ext(dfield);
+			}
+		}
+	}
+
+	size = rec_get_converted_size_comp_prefix(
+		index, tuple->fields, tuple->n_fields,
+		index->n_nullable, &extra_size) - REC_N_NEW_EXTRA_BYTES;
+	ut_ad(extra_size >= REC_N_NEW_EXTRA_BYTES);
+	extra_size -= REC_N_NEW_EXTRA_BYTES;;
+
+	mrec_size = ROW_LOG_HEADER_SIZE + size + (extra_size >= 0x80);
+
+	if (insert || index->online_log->same_pk) {
+		ut_ad(!old_pk);
+		old_pk_extra_size = old_pk_size = 0;
+	} else {
+		ut_ad(old_pk);
+		ut_ad(old_pk->n_fields == 2 + old_pk->n_fields_cmp);
+		ut_ad(DATA_TRX_ID_LEN == dtuple_get_nth_field(
+			      old_pk, old_pk->n_fields - 2)->len);
+		ut_ad(DATA_ROLL_PTR_LEN == dtuple_get_nth_field(
+			      old_pk, old_pk->n_fields - 1)->len);
+
+		old_pk_size = rec_get_converted_size_comp_prefix(
+			new_index, old_pk->fields, old_pk->n_fields,
+			0, &old_pk_extra_size) - REC_N_NEW_EXTRA_BYTES;
+		ut_ad(old_pk_extra_size >= REC_N_NEW_EXTRA_BYTES);
+		old_pk_extra_size -= REC_N_NEW_EXTRA_BYTES;
+		ut_ad(old_pk_extra_size < 0x100);
+		mrec_size += 1/*old_pk_extra_size*/ + old_pk_size;
+	}
+
+	if (byte* b = row_log_table_open(index->online_log,
+					 mrec_size, &avail_size)) {
+		*b++ = insert ? ROW_T_INSERT : ROW_T_UPDATE;
+
+		if (old_pk_size) {
+			*b++ = old_pk_extra_size;
+
+			rec_convert_dtuple_to_rec_comp(
+				b + old_pk_extra_size, 0, new_index,
+				REC_STATUS_ORDINARY,
+				old_pk->fields, old_pk->n_fields, 0);
+			b += old_pk_size;
+		}
+
+		if (extra_size < 0x80) {
+			*b++ = (byte) extra_size;
+		} else {
+			ut_ad(extra_size < 0x8000);
+			*b++ = (byte) (0x80 | (extra_size >> 8));
+			*b++ = (byte) extra_size;
+		}
+
+		rec_convert_dtuple_to_rec_comp(
+			b + extra_size, 0, index, REC_STATUS_ORDINARY,
+			tuple->fields, tuple->n_fields, index->n_nullable);
+		b += size;
+
+		row_log_table_close(
+			index->online_log, b, mrec_size, avail_size);
+	}
+
+	mem_heap_free(heap);
+}
+
+/******************************************************//**
+Logs an insert or update to a table that is being rebuilt. */
+static __attribute__((nonnull(1,2,3)))
+void
 row_log_table_low(
 /*==============*/
 	const rec_t*	rec,	/*!< in: clustered index leaf page record,
@@ -532,6 +660,9 @@ row_log_table_low(
 	ut_ad(rw_lock_own(&index->lock, RW_LOCK_SHARED)
 	      || rw_lock_own(&index->lock, RW_LOCK_EX));
 #endif /* UNIV_SYNC_DEBUG */
+	ut_ad(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
+	ut_ad(page_is_leaf(page_align(rec)));
+	ut_ad(!page_is_comp(page_align(rec)) == !rec_offs_comp(offsets));
 
 	if (dict_index_is_corrupted(index)
 	    || !dict_index_is_online_ddl(index)
@@ -539,14 +670,17 @@ row_log_table_low(
 		return;
 	}
 
-	if (rec_offs_comp(offsets)) {
-		ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY);
-
-		omit_size = REC_N_NEW_EXTRA_BYTES;
-	} else {
-		omit_size = REC_N_OLD_EXTRA_BYTES;
+	if (!rec_offs_comp(offsets)) {
+		row_log_table_low_redundant(
+			rec, index, offsets, insert, old_pk, new_index);
+		return;
 	}
 
+	ut_ad(page_is_comp(page_align(rec)));
+	ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY);
+
+	omit_size = REC_N_NEW_EXTRA_BYTES;
+
 	extra_size = rec_offs_extra_size(offsets) - omit_size;
 
 	mrec_size = rec_offs_size(offsets) - omit_size

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-wl6255 branch (marko.makela:3907 to 3909) WL#6255marko.makela30 May