From ec248f78cf896fbaf76dc3c6752dc2226a842c2c Mon Sep 17 00:00:00 2001
From: "heikki@hundin.mysql.fi" <>
Date: Fri, 25 Feb 2005 22:35:33 +0200
Subject: [PATCH] trx0undo.h, trx0undo.c, trx0trx.c, trx0roll.c:   Make
 InnoDB-5.0.3 to process log records of 4.1 undo log header create and reuse
 just like in 4.1; storing XID to the start of the undo log is a separately
 logged operation; this conforms to Rule 3 of InnoDB redo logging

---
 innobase/include/trx0undo.h |  40 +++----
 innobase/trx/trx0roll.c     |   2 +-
 innobase/trx/trx0trx.c      |  81 +++++--------
 innobase/trx/trx0undo.c     | 229 ++++++++++++++++++++----------------
 4 files changed, 174 insertions(+), 178 deletions(-)

diff --git a/innobase/include/trx0undo.h b/innobase/include/trx0undo.h
index fce62e46046..bd7337e4f90 100644
--- a/innobase/include/trx0undo.h
+++ b/innobase/include/trx0undo.h
@@ -307,23 +307,6 @@ trx_undo_parse_discard_latest(
 	byte*	end_ptr,/* in: buffer end */
 	page_t*	page,	/* in: page or NULL */
 	mtr_t*	mtr);	/* in: mtr or NULL */
-/************************************************************************
-Write X/Open XA Transaction Identification (XID) to undo log header */
-
-void
-trx_undo_write_xid(
-/*===============*/
-	trx_ulogf_t*	log_hdr,/* in: undo log header */
-	XID*		xid);	/* in: X/Open XA Transaction Identification */
-
-/************************************************************************
-Read X/Open XA Transaction Identification (XID) from undo log header */
-
-void
-trx_undo_read_xid(
-/*==============*/
-	trx_ulogf_t*	log_hdr,/* in: undo log header */
-	XID*		xid);	/* out: X/Open XA Transaction Identification */
 
 /* Types of an undo log segment */
 #define	TRX_UNDO_INSERT		1	/* contains undo entries for inserts */
@@ -419,7 +402,8 @@ struct trx_undo_struct{
 #define TRX_UNDO_PAGE_HDR_SIZE	(6 + FLST_NODE_SIZE)
 
 /* An update undo segment with just one page can be reused if it has
-< this number bytes used */
+< this number bytes used; we must leave space at least for one new undo
+log header on the page */
 
 #define TRX_UNDO_PAGE_REUSE_LIMIT	(3 * UNIV_PAGE_SIZE / 4)
 
@@ -488,17 +472,25 @@ page of an update undo log segment. */
 #define TRX_UNDO_HISTORY_NODE	34	/* If the log is put to the history
 					list, the file list node is here */
 /*-------------------------------------------------------------*/
+#define TRX_UNDO_LOG_OLD_HDR_SIZE (34 + FLST_NODE_SIZE)
+
+/* Note: the writing of the undo log old header is coded by a log record
+MLOG_UNDO_HDR_CREATE or MLOG_UNDO_HDR_REUSE. The appending of an XID to the
+header is logged separately. In this sense, the XID is not really a member
+of the undo log header. TODO: do not append the XID to the log header if XA
+is not needed by the user. The XID wastes about 150 bytes of space in every
+undo log. In the history list we may have millions of undo logs, which means
+quite a large overhead. */
+
 /* X/Open XA Transaction Identification (XID)                  */
 
-#define	TRX_UNDO_XA_FORMAT	(34 + FLST_NODE_SIZE)
+#define	TRX_UNDO_XA_FORMAT	(TRX_UNDO_LOG_OLD_HDR_SIZE)
 #define	TRX_UNDO_XA_TRID_LEN	(TRX_UNDO_XA_FORMAT + 4)
 #define	TRX_UNDO_XA_BQUAL_LEN	(TRX_UNDO_XA_TRID_LEN + 4)
 #define	TRX_UNDO_XA_XID		(TRX_UNDO_XA_BQUAL_LEN + 4)
-#define	TRX_UNDO_XA_LEN		(TRX_UNDO_XA_XID + XIDDATASIZE)
-
-/*-------------------------------------------------------------*/
-#define	TRX_UNDO_LOG_HDR_SIZE	(TRX_UNDO_XA_LEN)
-/*-------------------------------------------------------------*/
+/*--------------------------------------------------------------*/
+#define TRX_UNDO_LOG_XA_HDR_SIZE (TRX_UNDO_XA_XID + XIDDATASIZE)
+				/* Total size of the header with the XA XID */
 
 #ifndef UNIV_NONINL
 #include "trx0undo.ic"
diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c
index e57057de7ff..559c2cb5128 100644
--- a/innobase/trx/trx0roll.c
+++ b/innobase/trx/trx0roll.c
@@ -950,7 +950,7 @@ try_again:
 		if (progress_pct != trx_roll_progress_printed_pct) {
 			if (trx_roll_progress_printed_pct == 0) {
 				fprintf(stderr,
-"\nInnoDB: Progress in percents: %lu\n", (ulong) progress_pct);
+"\nInnoDB: Progress in percents: %lu", (ulong) progress_pct);
 			} else {
 				fprintf(stderr,
 				" %lu", (ulong) progress_pct);
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 40e12f206dc..bc9775c21fb 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -162,7 +162,7 @@ trx_create(
 	trx->read_view = NULL;
 
 	/* Set X/Open XA transaction identification to NULL */
-	memset(&trx->xid,0,sizeof(trx->xid));
+	memset(&trx->xid, 0, sizeof(trx->xid));
 	trx->xid.formatID = -1;
 
 	return(trx);
@@ -436,16 +436,12 @@ trx_lists_init_at_db_start(void)
 				if (undo->state == TRX_UNDO_PREPARED) {
 
 					fprintf(stderr,
-"InnoDB: Transaction %lu %lu was in the XA prepared state. We change it to\n"
-"InnoDB: the 'active' state, so that InnoDB's true-and-tested crash\n"
-"InnoDB: recovery will roll it back. If mysqld refuses to start after\n"
-"InnoDB: this, you may be able to resolve the problem by moving the binlog\n"
-"InnoDB: files to a safe place, and deleting all binlog files and the binlog\n"
-"InnoDB: .index file from the datadir.\n", ut_dulint_get_high(trx->id),
-					   ut_dulint_get_low(trx->id));
+"InnoDB: Transaction %lu %lu was in the XA prepared state.\n",
+					ut_dulint_get_high(trx->id),
+					ut_dulint_get_low(trx->id));
 
-					/* trx->conc_state = TRX_PREPARED; */
-					trx->conc_state =
+				/*	trx->conc_state = TRX_PREPARED; */
+				 	trx->conc_state =
 						TRX_ACTIVE;
 				} else {
 					trx->conc_state =
@@ -504,13 +500,9 @@ trx_lists_init_at_db_start(void)
 					if (undo->state == TRX_UNDO_PREPARED) {
 
 					fprintf(stderr,
-"InnoDB: Transaction %lu %lu was in the XA prepared state. We change it to\n"
-"InnoDB: the 'active' state, so that InnoDB's true-and-tested crash\n"
-"InnoDB: recovery will roll it back. If mysqld refuses to start after\n"
-"InnoDB: this, you may be able to resolve the problem by moving the binlog\n"
-"InnoDB: files to a safe place, and deleting all binlog files and the binlog\n"
-"InnoDB: .index file from the datadir.\n", ut_dulint_get_high(trx->id),
-					   ut_dulint_get_low(trx->id));
+"InnoDB: Transaction %lu %lu was in the XA prepared state.\n",
+					ut_dulint_get_high(trx->id),
+					ut_dulint_get_low(trx->id));
 
 					/* trx->conc_state = TRX_PREPARED; */
 					trx->conc_state =
@@ -786,8 +778,8 @@ trx_commit_off_kernel(
 		mutex_enter(&kernel_mutex);
 	}
 
-	ut_ad(trx->conc_state == TRX_ACTIVE || trx->conc_state == TRX_PREPARED);
-
+	ut_ad(trx->conc_state == TRX_ACTIVE
+					|| trx->conc_state == TRX_PREPARED);
 #ifdef UNIV_SYNC_DEBUG
 	ut_ad(mutex_own(&kernel_mutex));
 #endif /* UNIV_SYNC_DEBUG */
@@ -1744,10 +1736,10 @@ trx_prepare_off_kernel(
 	trx_t*	trx)	/* in: transaction */
 {
 	page_t*		update_hdr_page;
-	dulint		lsn;
 	trx_rseg_t*	rseg;
 	trx_undo_t*	undo;
 	ibool		must_flush_log	= FALSE;
+	dulint		lsn;
 	mtr_t		mtr;
 	
 #ifdef UNIV_SYNC_DEBUG
@@ -1765,35 +1757,36 @@ trx_prepare_off_kernel(
 		must_flush_log = TRUE;
 
 		/* Change the undo log segment states from TRX_UNDO_ACTIVE
-		to some other state: these modifications to the file data
-		structure define the transaction as prepared in the file
-		based world, at the serialization point of the log sequence
-		number lsn obtained below. */
+		to TRX_UNDO_PREPARED: these modifications to the file data
+		structure define the transaction as prepared in the
+		file-based world, at the serialization point of lsn. */
 
 		mutex_enter(&(rseg->mutex));
 			
 		if (trx->insert_undo != NULL) {
 			trx_undo_set_state_at_prepare(trx, trx->insert_undo,
-							   &mtr);
+							  		&mtr);
 		}
 
 		undo = trx->update_undo;
 
 		if (undo) {
-
 			/* It is not necessary to obtain trx->undo_mutex here
 			because only a single OS thread is allowed to do the
 			transaction prepare for this transaction. */
 					
-			update_hdr_page = trx_undo_set_state_at_prepare(trx,								undo, &mtr);
+			update_hdr_page = trx_undo_set_state_at_prepare(trx,
+								undo, &mtr);
 		}
 
 		mutex_exit(&(rseg->mutex));
 
 		/*--------------*/
-		mtr_commit(&mtr);
+		mtr_commit(&mtr);	/* This mtr commit makes the
+					transaction prepared in the file-based
+					world */
 		/*--------------*/
-		lsn = mtr.end_lsn;
+ 		lsn = mtr.end_lsn;
 
 		mutex_enter(&kernel_mutex);
 	}
@@ -1806,13 +1799,6 @@ trx_prepare_off_kernel(
 	trx->conc_state = TRX_PREPARED;
 	/*--------------------------------------*/
 
-	if (trx->read_view) {
-		read_view_close(trx->read_view);
-
-		mem_heap_empty(trx->read_view_heap);
-		trx->read_view = NULL;
-	}
-
 	if (must_flush_log) {
 
 		mutex_exit(&kernel_mutex);
@@ -1834,7 +1820,7 @@ Does the transaction prepare for MySQL. */
 
 ulint
 trx_prepare_for_mysql(
-/*=================*/
+/*====-=============*/
 			/* out: 0 or error number */
 	trx_t*	trx)	/* in: trx handle */
 {
@@ -1881,9 +1867,8 @@ trx_recover_for_mysql(
 	fprintf(stderr,
 		"  InnoDB: Starting recovery for XA transactions...\n");
 
-
-	/* We should set those transactions which are in
-	the prepared state to the xid_list */
+	/* We should set those transactions which are in the prepared state
+	to the xid_list */
 
 	mutex_enter(&kernel_mutex);
 
@@ -1891,14 +1876,7 @@ trx_recover_for_mysql(
 
 	while (trx) {
 		if (trx->conc_state == TRX_PREPARED) {
-			xid_list[count].formatID = trx->xid.formatID;
-			xid_list[count].gtrid_length = trx->xid.gtrid_length;
-			xid_list[count].bqual_length = trx->xid.bqual_length;
-
-			memcpy(xid_list[count].data,
-					trx->xid.data,
-					trx->xid.gtrid_length + 
-					trx->xid.bqual_length);
+			xid_list[count] = trx->xid;
 
 			ut_print_timestamp(stderr);
 			fprintf(stderr,
@@ -1935,15 +1913,16 @@ trx_recover_for_mysql(
 This function is used to find one X/Open XA distributed transaction
 which is in the prepared state */
 
-trx_t * 
+trx_t*
 trx_get_trx_by_xid(
 /*===============*/
 			/* out: trx or NULL */
-	XID*	xid)	/*  in: X/Open XA Transaction Idenfication */
+	XID*	xid)	/* in: X/Open XA Transaction Idenfication */
 {
 	trx_t*	trx;
 
 	if (xid == NULL) {
+
 		return (NULL);
 	}
  
@@ -1972,6 +1951,7 @@ trx_get_trx_by_xid(
 
 	if (trx) {
 		if (trx->conc_state != TRX_PREPARED) {
+
 			return(NULL);
 		}
 
@@ -1980,4 +1960,3 @@ trx_get_trx_by_xid(
 		return(NULL);
 	}
 }
-
diff --git a/innobase/trx/trx0undo.c b/innobase/trx/trx0undo.c
index e9296d1d9c7..545e1b77fee 100644
--- a/innobase/trx/trx0undo.c
+++ b/innobase/trx/trx0undo.c
@@ -100,9 +100,11 @@ trx_undo_mem_create(
 				is created */	
 	XID*		xid,    /* in: X/Open XA transaction identification*/
 	ulint		page_no,/* in: undo log header page number */
-	ulint		offset);	/* in: undo log header byte offset on page */
+	ulint		offset);/* in: undo log header byte offset on page */
 /*******************************************************************
-Initializes a cached insert undo log header page for new use. */
+Initializes a cached insert undo log header page for new use. NOTE that this
+function has its own log record type MLOG_UNDO_HDR_REUSE. You must NOT change
+the operation of this function! */
 static
 ulint
 trx_undo_insert_header_reuse(
@@ -111,7 +113,6 @@ trx_undo_insert_header_reuse(
 	page_t*	undo_page,	/* in: insert undo log segment header page,
 				x-latched */
 	dulint	trx_id,		/* in: transaction id */
-	XID*	xid,		/* in: X/Open XA transaction identification*/
 	mtr_t*	mtr);		/* in: mtr */
 /**************************************************************************
 If an update undo log can be discarded immediately, this function frees the
@@ -184,7 +185,8 @@ trx_undo_get_prev_rec(
 	/* We have to go to the previous undo log page to look for the
 	previous record */
 
-	return(trx_undo_get_prev_rec_from_prev_page(rec, page_no, offset, mtr));
+	return(trx_undo_get_prev_rec_from_prev_page(rec, page_no, offset,
+									mtr));
 }
 
 /***************************************************************************
@@ -476,18 +478,19 @@ trx_undo_header_create_log(
 }	
 
 /*******************************************************************
-Creates a new undo log header in file. */
+Creates a new undo log header in file. NOTE that this function has its own
+log record type MLOG_UNDO_HDR_CREATE. You must NOT change the operation of
+this function! */
 static
 ulint
 trx_undo_header_create(
 /*===================*/
 				/* out: header byte offset on page */
 	page_t*	undo_page,	/* in: undo log segment header page,
-				x-latched; it is assumed that there is
-				TRX_UNDO_LOG_HDR_SIZE bytes free space
+				x-latched; it is assumed that there are
+				TRX_UNDO_LOG_XA_HDR_SIZE bytes free space
 				on it */
 	dulint	trx_id,		/* in: transaction id */
-	XID*	xid,		/* in: X/Open XA XID */
 	mtr_t*	mtr)		/* in: mtr */
 {
 	trx_upagef_t*	page_hdr;
@@ -507,9 +510,9 @@ trx_undo_header_create(
 
 	log_hdr = undo_page + free;
 	
-	new_free = free + TRX_UNDO_LOG_HDR_SIZE;
+	new_free = free + TRX_UNDO_LOG_OLD_HDR_SIZE;
 
-	ut_ad(new_free <= UNIV_PAGE_SIZE);
+	ut_a(free + TRX_UNDO_LOG_XA_HDR_SIZE < UNIV_PAGE_SIZE - 100);
 	
 	mach_write_to_2(page_hdr + TRX_UNDO_PAGE_START, new_free);
 
@@ -534,30 +537,104 @@ trx_undo_header_create(
 	mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id);
 	mach_write_to_2(log_hdr + TRX_UNDO_LOG_START, new_free);
 
-	/* If X/Open XID exits in the log header we store a
-	flag of it in upper byte of dict operation flag. */
-
-	if (xid != NULL && xid->formatID != -1) {
-		mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, TRUE);
-	} else {
-		mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
-	}
-
+	mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
 	mach_write_to_1(log_hdr + TRX_UNDO_DICT_TRANS, FALSE);
+
 	mach_write_to_2(log_hdr + TRX_UNDO_NEXT_LOG, 0);
 	mach_write_to_2(log_hdr + TRX_UNDO_PREV_LOG, prev_log);
 
-	/* Write X/Open XA transaction identification if exists */
-
-	if (xid && xid->formatID != -1) {
-		trx_undo_write_xid(log_hdr, xid);
-	}
-
+	/* Write the log record about the header creation */
 	trx_undo_header_create_log(undo_page, trx_id, mtr);
 	
 	return(free);
 }
 
+/************************************************************************
+Write X/Open XA Transaction Identification (XID) to undo log header */
+static
+void
+trx_undo_write_xid(
+/*===============*/
+	trx_ulogf_t*	log_hdr,/* in: undo log header */
+	XID*		xid,	/* in: X/Open XA Transaction Identification */
+	mtr_t*		mtr)	/* in: mtr */
+{
+	mlog_write_ulint(log_hdr + TRX_UNDO_XA_FORMAT, xid->formatID,
+							MLOG_4BYTES, mtr);
+
+	mlog_write_ulint(log_hdr + TRX_UNDO_XA_TRID_LEN, xid->gtrid_length,
+							MLOG_4BYTES, mtr);
+
+	mlog_write_ulint(log_hdr + TRX_UNDO_XA_BQUAL_LEN, xid->bqual_length,
+							MLOG_4BYTES, mtr);
+
+	mlog_write_string(log_hdr + TRX_UNDO_XA_XID, xid->data,
+							XIDDATASIZE, mtr);
+}
+
+/************************************************************************
+Read X/Open XA Transaction Identification (XID) from undo log header */
+static
+void
+trx_undo_read_xid(
+/*==============*/
+	trx_ulogf_t*	log_hdr,/* in: undo log header */
+	XID*		xid)	/* out: X/Open XA Transaction Identification */
+{
+	ulint i;
+
+	xid->formatID = mach_read_from_4(log_hdr + TRX_UNDO_XA_FORMAT);
+	
+	xid->gtrid_length = mach_read_from_4(log_hdr + TRX_UNDO_XA_TRID_LEN);
+
+	xid->bqual_length = mach_read_from_4(log_hdr + TRX_UNDO_XA_BQUAL_LEN);
+
+	for (i = 0; i < XIDDATASIZE; i++) {
+		xid->data[i] = (char)mach_read_from_1(log_hdr + 
+							TRX_UNDO_XA_XID + i);
+	}
+}
+
+/*******************************************************************
+Adds the XA XID after an undo log old-style header. */
+static
+void
+trx_undo_header_add_xid(
+/*====================*/
+	page_t*		undo_page,/* in: undo log segment header page */
+	trx_ulogf_t*	log_hdr,/* in: undo log header */
+	XID*		xid,	/* in: X/Open XA transaction identification */
+	mtr_t*		mtr)	/* in: mtr */
+{
+	trx_upagef_t*	page_hdr;
+	ulint		free;
+	ulint		new_free;
+
+	page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
+
+	free = mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE);
+
+	/* free is now the end offset of the old style undo log header */
+
+	ut_a(free == (ulint)(log_hdr - undo_page) + TRX_UNDO_LOG_OLD_HDR_SIZE);
+
+	new_free = free + (TRX_UNDO_LOG_XA_HDR_SIZE
+						- TRX_UNDO_LOG_OLD_HDR_SIZE);
+	trx_undo_write_xid(log_hdr, xid, mtr);
+
+	/* Now that we added the XID after the header, update the free offset
+	fields on the undo log page and in the undo log header */
+
+	mlog_write_ulint(page_hdr + TRX_UNDO_PAGE_START, new_free,
+							MLOG_2BYTES, mtr);
+
+	mlog_write_ulint(page_hdr + TRX_UNDO_PAGE_FREE, new_free,
+							MLOG_2BYTES, mtr);
+
+	mlog_write_ulint(log_hdr + TRX_UNDO_LOG_START, new_free,
+							MLOG_2BYTES, mtr);
+}
+
 /**************************************************************************
 Writes the mtr log entry of an undo log header reuse. */
 UNIV_INLINE
@@ -587,11 +664,6 @@ trx_undo_parse_page_header(
 	mtr_t*	mtr)	/* in: mtr or NULL */
 {
 	dulint	trx_id;
-	XID	xid;
-
-	/* Set X/Open XA transaction identification to NULL */
-	memset(&xid, 0, sizeof(xid));
-	xid.formatID = -1;
 	
 	ptr = mach_dulint_parse_compressed(ptr, end_ptr, &trx_id);
 
@@ -602,10 +674,10 @@ trx_undo_parse_page_header(
 
 	if (page) {
 		if (type == MLOG_UNDO_HDR_CREATE) {
-			trx_undo_header_create(page, trx_id, &xid, mtr);
+			trx_undo_header_create(page, trx_id, mtr);
 		} else {
 			ut_ad(type == MLOG_UNDO_HDR_REUSE);
-			trx_undo_insert_header_reuse(page, trx_id, &xid, mtr);
+			trx_undo_insert_header_reuse(page, trx_id, mtr);
 		}
 	}
 
@@ -613,7 +685,9 @@ trx_undo_parse_page_header(
 }	
 
 /*******************************************************************
-Initializes a cached insert undo log header page for new use. */
+Initializes a cached insert undo log header page for new use. NOTE that this
+function has its own log record type MLOG_UNDO_HDR_REUSE. You must NOT change
+the operation of this function! */
 static
 ulint
 trx_undo_insert_header_reuse(
@@ -622,7 +696,6 @@ trx_undo_insert_header_reuse(
 	page_t*	undo_page,	/* in: insert undo log segment header page,
 				x-latched */
 	dulint	trx_id,		/* in: transaction id */
-	XID*	xid,		/* in: X/Open XA transaction identification */
 	mtr_t*	mtr)		/* in: mtr */
 {
 	trx_upagef_t*	page_hdr;
@@ -638,9 +711,11 @@ trx_undo_insert_header_reuse(
 
 	free = TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE;
 
+	ut_a(free + TRX_UNDO_LOG_XA_HDR_SIZE < UNIV_PAGE_SIZE - 100);
+
 	log_hdr = undo_page + free;
 	
-	new_free = free + TRX_UNDO_LOG_HDR_SIZE;
+	new_free = free + TRX_UNDO_LOG_OLD_HDR_SIZE;
 
 	/* Insert undo data is not needed after commit: we may free all
 	the space on the page */
@@ -660,18 +735,10 @@ trx_undo_insert_header_reuse(
 	mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id);
 	mach_write_to_2(log_hdr + TRX_UNDO_LOG_START, new_free);
 
-	/* If X/Open XID exits in the log header we store it
-	to log header. */
-
-	if (xid && xid->formatID != -1) {
-		mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, TRUE); 
-
-		trx_undo_write_xid(log_hdr, xid);
-	} else {
-		mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
-	}
-
+	mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
 	mach_write_to_1(log_hdr + TRX_UNDO_DICT_TRANS, FALSE);
+
+	/* Write the log record MLOG_UNDO_HDR_REUSE */
 	trx_undo_insert_header_reuse_log(undo_page, trx_id, mtr);
 	
 	return(free);
@@ -751,52 +818,6 @@ trx_undo_discard_latest_update_undo(
 	trx_undo_discard_latest_log(undo_page, mtr);
 }
 
-/************************************************************************
-Write X/Open XA Transaction Identification (XID) to undo log header */
-
-void
-trx_undo_write_xid(
-/*===============*/
-	trx_ulogf_t*	log_hdr,/* in: undo log header */
-	XID*		xid)	/* in: X/Open XA Transaction Identification */
-{
-	ulint i;
-
-	mach_write_to_4(log_hdr + TRX_UNDO_XA_FORMAT, xid->formatID);
-
-	mach_write_to_4(log_hdr + TRX_UNDO_XA_TRID_LEN, xid->gtrid_length);
-
-	mach_write_to_4(log_hdr + TRX_UNDO_XA_BQUAL_LEN, xid->bqual_length);
-
-	for(i=0; i < XIDDATASIZE; i++) {
-		mach_write_to_1(log_hdr + TRX_UNDO_XA_XID + i,
-					(ulint)(xid->data[i]));
-	}
-}
-
-/************************************************************************
-Read X/Open XA Transaction Identification (XID) from undo log header */
-
-void
-trx_undo_read_xid(
-/*==============*/
-	trx_ulogf_t*	log_hdr,/* in: undo log header */
-	XID*		xid)	/* out: X/Open XA Transaction Identification */
-{
-	ulint i;
-
-	xid->formatID = mach_read_from_4(log_hdr + TRX_UNDO_XA_FORMAT);
-	
-	xid->gtrid_length = mach_read_from_4(log_hdr + TRX_UNDO_XA_TRID_LEN);
-
-	xid->bqual_length = mach_read_from_4(log_hdr + TRX_UNDO_XA_BQUAL_LEN);
-
-	for(i=0; i < XIDDATASIZE; i++) {
-		xid->data[i] = (char)mach_read_from_1(log_hdr + 
-							TRX_UNDO_XA_XID +i);
-	}
-}
-
 /************************************************************************
 Tries to add a page to the undo log segment where the undo log is placed. */
 
@@ -1228,7 +1249,7 @@ trx_undo_mem_create_at_db_start(
 	xid_exists = mtr_read_ulint(undo_header + TRX_UNDO_XID_EXISTS, 
 						MLOG_1BYTE, mtr);
 
-	/* Read X/Open XA transaction identification if exists or
+	/* Read X/Open XA transaction identification if it exists, or
 	set it to NULL. */
 
 	memset(&xid, 0, sizeof(xid));
@@ -1242,7 +1263,6 @@ trx_undo_mem_create_at_db_start(
 
 	undo = trx_undo_mem_create(rseg, id, type, trx_id, &xid, 
 						page_no, offset);
-	
 	mutex_exit(&(rseg->mutex));
 
 	undo->dict_operation = 	mtr_read_ulint(
@@ -1510,11 +1530,12 @@ trx_undo_create(
 
 	page_no = buf_frame_get_page_no(undo_page);
 	
-	offset = trx_undo_header_create(undo_page, trx_id, xid, mtr);	
+	offset = trx_undo_header_create(undo_page, trx_id, mtr);
 
-	undo = trx_undo_mem_create(rseg, id, type, trx_id, xid ,
+	trx_undo_header_add_xid(undo_page, undo_page + offset, xid, mtr);
+
+	undo = trx_undo_mem_create(rseg, id, type, trx_id, xid,
 							page_no, offset);
-	
 	return(undo);
 }
 
@@ -1533,7 +1554,7 @@ trx_undo_reuse_cached(
 				TRX_UNDO_UPDATE */
 	dulint		trx_id,	/* in: id of the trx for which the undo log
 				is used */	
-	XID*		xid,	/* in: X/Open XA transaction identification*/
+	XID*		xid,	/* in: X/Open XA transaction identification */
 	mtr_t*		mtr)	/* in: mtr */
 {
 	trx_undo_t*	undo;
@@ -1577,14 +1598,17 @@ trx_undo_reuse_cached(
 	undo_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr);
 
 	if (type == TRX_UNDO_INSERT) {
-		offset = trx_undo_insert_header_reuse(undo_page, trx_id, 
-								xid, mtr);
+		offset = trx_undo_insert_header_reuse(undo_page, trx_id, mtr);
+		trx_undo_header_add_xid(undo_page, undo_page + offset, xid,
+									mtr);
 	} else {
 		ut_a(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
 					+ TRX_UNDO_PAGE_TYPE)
 						== TRX_UNDO_UPDATE);
 
-		offset = trx_undo_header_create(undo_page, trx_id, xid, mtr);
+		offset = trx_undo_header_create(undo_page, trx_id, mtr);
+		trx_undo_header_add_xid(undo_page, undo_page + offset, xid,
+									mtr);
 	}
 	
 	trx_undo_mem_init_for_reuse(undo, trx_id, xid, offset);
@@ -1782,7 +1806,8 @@ trx_undo_set_state_at_prepare(
 	mlog_write_ulint(undo_header + TRX_UNDO_XID_EXISTS,
 					TRUE, MLOG_1BYTE, mtr);
 
-	trx_undo_write_xid(undo_header, &undo->xid);	
+	trx_undo_write_xid(undo_header, &undo->xid, mtr);	
+
 	return(undo_page);
 }