mariadb/include/trx0sys.ic
marko 87cf4a3a02 branches/zip: Merge revisions 4994:5148 from branches/5.1:
------------------------------------------------------------------------
  r5126 | vasil | 2009-05-26 16:57:12 +0300 (Tue, 26 May 2009) | 9 lines

  branches/5.1:

  Preparation for the fix of
  Bug#45097 Hang during recovery, redo logs for doublewrite buffer pages

  Non-functional change: move FSP_* macros from fsp0fsp.h to a new file
  fsp0types.h. This is needed in order to be able to use FSP_EXTENT_SIZE
  in mtr0log.ic.
  ------------------------------------------------------------------------
  r5127 | vasil | 2009-05-26 17:05:43 +0300 (Tue, 26 May 2009) | 9 lines

  branches/5.1:

  Preparation for the fix of
  Bug#45097 Hang during recovery, redo logs for doublewrite buffer pages

  Do not include unnecessary headers mtr0log.h and fut0lst.h in trx0sys.h
  and include fsp0fsp.h just before it is needed. This is needed in order
  to be able to use TRX_SYS_SPACE in mtr0log.ic.
  ------------------------------------------------------------------------
  r5128 | vasil | 2009-05-26 17:26:37 +0300 (Tue, 26 May 2009) | 7 lines

  branches/5.1:

  Fix Bug#45097 Hang during recovery, redo logs for doublewrite buffer pages

  Do not write redo log for the pages in the doublewrite buffer. Also, do not
  make a dummy change to the page because this is not needed.
  ------------------------------------------------------------------------
2009-05-27 10:46:42 +00:00

387 lines
10 KiB
Text

/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. 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
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/**************************************************//**
@file include/trx0sys.ic
Transaction system
Created 3/26/1996 Heikki Tuuri
*******************************************************/
#include "trx0trx.h"
#include "data0type.h"
#ifndef UNIV_HOTBACKUP
# include "srv0srv.h"
# include "mtr0log.h"
/* The typedef for rseg slot in the file copy */
typedef byte trx_sysf_rseg_t;
/* Rollback segment specification slot offsets */
/*-------------------------------------------------------------*/
#define TRX_SYS_RSEG_SPACE 0 /* space where the the segment
header is placed; starting with
MySQL/InnoDB 5.1.7, this is
UNIV_UNDEFINED if the slot is unused */
#define TRX_SYS_RSEG_PAGE_NO 4 /* page number where the the segment
header is placed; this is FIL_NULL
if the slot is unused */
/*-------------------------------------------------------------*/
/* Size of a rollback segment specification slot */
#define TRX_SYS_RSEG_SLOT_SIZE 8
/*****************************************************************//**
Writes the value of max_trx_id to the file based trx system header. */
UNIV_INTERN
void
trx_sys_flush_max_trx_id(void);
/*==========================*/
/***************************************************************//**
Checks if a page address is the trx sys header page.
@return TRUE if trx sys header page */
UNIV_INLINE
ibool
trx_sys_hdr_page(
/*=============*/
ulint space, /*!< in: space */
ulint page_no)/*!< in: page number */
{
if ((space == TRX_SYS_SPACE) && (page_no == TRX_SYS_PAGE_NO)) {
return(TRUE);
}
return(FALSE);
}
/***************************************************************//**
Gets the pointer in the nth slot of the rseg array.
@return pointer to rseg object, NULL if slot not in use */
UNIV_INLINE
trx_rseg_t*
trx_sys_get_nth_rseg(
/*=================*/
trx_sys_t* sys, /*!< in: trx system */
ulint n) /*!< in: index of slot */
{
ut_ad(mutex_own(&(kernel_mutex)));
ut_ad(n < TRX_SYS_N_RSEGS);
return(sys->rseg_array[n]);
}
/***************************************************************//**
Sets the pointer in the nth slot of the rseg array. */
UNIV_INLINE
void
trx_sys_set_nth_rseg(
/*=================*/
trx_sys_t* sys, /*!< in: trx system */
ulint n, /*!< in: index of slot */
trx_rseg_t* rseg) /*!< in: pointer to rseg object, NULL if slot
not in use */
{
ut_ad(n < TRX_SYS_N_RSEGS);
sys->rseg_array[n] = rseg;
}
/**********************************************************************//**
Gets a pointer to the transaction system header and x-latches its page.
@return pointer to system header, page x-latched. */
UNIV_INLINE
trx_sysf_t*
trx_sysf_get(
/*=========*/
mtr_t* mtr) /*!< in: mtr */
{
buf_block_t* block;
trx_sysf_t* header;
ut_ad(mtr);
block = buf_page_get(TRX_SYS_SPACE, 0, TRX_SYS_PAGE_NO,
RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);
header = TRX_SYS + buf_block_get_frame(block);
return(header);
}
/*****************************************************************//**
Gets the space of the nth rollback segment slot in the trx system
file copy.
@return space id */
UNIV_INLINE
ulint
trx_sysf_rseg_get_space(
/*====================*/
trx_sysf_t* sys_header, /*!< in: trx sys header */
ulint i, /*!< in: slot index == rseg id */
mtr_t* mtr) /*!< in: mtr */
{
ut_ad(mutex_own(&(kernel_mutex)));
ut_ad(sys_header);
ut_ad(i < TRX_SYS_N_RSEGS);
return(mtr_read_ulint(sys_header + TRX_SYS_RSEGS
+ i * TRX_SYS_RSEG_SLOT_SIZE
+ TRX_SYS_RSEG_SPACE, MLOG_4BYTES, mtr));
}
/*****************************************************************//**
Gets the page number of the nth rollback segment slot in the trx system
header.
@return page number, FIL_NULL if slot unused */
UNIV_INLINE
ulint
trx_sysf_rseg_get_page_no(
/*======================*/
trx_sysf_t* sys_header, /*!< in: trx system header */
ulint i, /*!< in: slot index == rseg id */
mtr_t* mtr) /*!< in: mtr */
{
ut_ad(sys_header);
ut_ad(mutex_own(&(kernel_mutex)));
ut_ad(i < TRX_SYS_N_RSEGS);
return(mtr_read_ulint(sys_header + TRX_SYS_RSEGS
+ i * TRX_SYS_RSEG_SLOT_SIZE
+ TRX_SYS_RSEG_PAGE_NO, MLOG_4BYTES, mtr));
}
/*****************************************************************//**
Sets the space id of the nth rollback segment slot in the trx system
file copy. */
UNIV_INLINE
void
trx_sysf_rseg_set_space(
/*====================*/
trx_sysf_t* sys_header, /*!< in: trx sys file copy */
ulint i, /*!< in: slot index == rseg id */
ulint space, /*!< in: space id */
mtr_t* mtr) /*!< in: mtr */
{
ut_ad(mutex_own(&(kernel_mutex)));
ut_ad(sys_header);
ut_ad(i < TRX_SYS_N_RSEGS);
mlog_write_ulint(sys_header + TRX_SYS_RSEGS
+ i * TRX_SYS_RSEG_SLOT_SIZE
+ TRX_SYS_RSEG_SPACE,
space,
MLOG_4BYTES, mtr);
}
/*****************************************************************//**
Sets the page number of the nth rollback segment slot in the trx system
header. */
UNIV_INLINE
void
trx_sysf_rseg_set_page_no(
/*======================*/
trx_sysf_t* sys_header, /*!< in: trx sys header */
ulint i, /*!< in: slot index == rseg id */
ulint page_no, /*!< in: page number, FIL_NULL if the
slot is reset to unused */
mtr_t* mtr) /*!< in: mtr */
{
ut_ad(mutex_own(&(kernel_mutex)));
ut_ad(sys_header);
ut_ad(i < TRX_SYS_N_RSEGS);
mlog_write_ulint(sys_header + TRX_SYS_RSEGS
+ i * TRX_SYS_RSEG_SLOT_SIZE
+ TRX_SYS_RSEG_PAGE_NO,
page_no,
MLOG_4BYTES, mtr);
}
#endif /* !UNIV_HOTBACKUP */
/*****************************************************************//**
Writes a trx id to an index page. In case that the id size changes in
some future version, this function should be used instead of
mach_write_... */
UNIV_INLINE
void
trx_write_trx_id(
/*=============*/
byte* ptr, /*!< in: pointer to memory where written */
trx_id_t id) /*!< in: id */
{
#if DATA_TRX_ID_LEN != 6
# error "DATA_TRX_ID_LEN != 6"
#endif
mach_write_to_6(ptr, id);
}
#ifndef UNIV_HOTBACKUP
/*****************************************************************//**
Reads a trx id from an index page. In case that the id size changes in
some future version, this function should be used instead of
mach_read_...
@return id */
UNIV_INLINE
trx_id_t
trx_read_trx_id(
/*============*/
const byte* ptr) /*!< in: pointer to memory from where to read */
{
#if DATA_TRX_ID_LEN != 6
# error "DATA_TRX_ID_LEN != 6"
#endif
return(mach_read_from_6(ptr));
}
/****************************************************************//**
Looks for the trx handle with the given id in trx_list.
@return the trx handle or NULL if not found */
UNIV_INLINE
trx_t*
trx_get_on_id(
/*==========*/
trx_id_t trx_id) /*!< in: trx id to search for */
{
trx_t* trx;
ut_ad(mutex_own(&(kernel_mutex)));
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
while (trx != NULL) {
if (0 == ut_dulint_cmp(trx_id, trx->id)) {
return(trx);
}
trx = UT_LIST_GET_NEXT(trx_list, trx);
}
return(NULL);
}
/****************************************************************//**
Returns the minumum trx id in trx list. This is the smallest id for which
the trx can possibly be active. (But, you must look at the trx->conc_state to
find out if the minimum trx id transaction itself is active, or already
committed.)
@return the minimum trx id, or trx_sys->max_trx_id if the trx list is empty */
UNIV_INLINE
trx_id_t
trx_list_get_min_trx_id(void)
/*=========================*/
{
trx_t* trx;
ut_ad(mutex_own(&(kernel_mutex)));
trx = UT_LIST_GET_LAST(trx_sys->trx_list);
if (trx == NULL) {
return(trx_sys->max_trx_id);
}
return(trx->id);
}
/****************************************************************//**
Checks if a transaction with the given id is active.
@return TRUE if active */
UNIV_INLINE
ibool
trx_is_active(
/*==========*/
trx_id_t trx_id) /*!< in: trx id of the transaction */
{
trx_t* trx;
ut_ad(mutex_own(&(kernel_mutex)));
if (ut_dulint_cmp(trx_id, trx_list_get_min_trx_id()) < 0) {
return(FALSE);
}
if (ut_dulint_cmp(trx_id, trx_sys->max_trx_id) >= 0) {
/* There must be corruption: we return TRUE because this
function is only called by lock_clust_rec_some_has_impl()
and row_vers_impl_x_locked_off_kernel() and they have
diagnostic prints in this case */
return(TRUE);
}
trx = trx_get_on_id(trx_id);
if (trx && (trx->conc_state == TRX_ACTIVE
|| trx->conc_state == TRX_PREPARED)) {
return(TRUE);
}
return(FALSE);
}
/*****************************************************************//**
Allocates a new transaction id.
@return new, allocated trx id */
UNIV_INLINE
trx_id_t
trx_sys_get_new_trx_id(void)
/*========================*/
{
trx_id_t id;
ut_ad(mutex_own(&kernel_mutex));
/* VERY important: after the database is started, max_trx_id value is
divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the following if
will evaluate to TRUE when this function is first time called,
and the value for trx id will be written to disk-based header!
Thus trx id values will not overlap when the database is
repeatedly started! */
if (ut_dulint_get_low(trx_sys->max_trx_id)
% TRX_SYS_TRX_ID_WRITE_MARGIN == 0) {
trx_sys_flush_max_trx_id();
}
id = trx_sys->max_trx_id;
UT_DULINT_INC(trx_sys->max_trx_id);
return(id);
}
/*****************************************************************//**
Allocates a new transaction number.
@return new, allocated trx number */
UNIV_INLINE
trx_id_t
trx_sys_get_new_trx_no(void)
/*========================*/
{
ut_ad(mutex_own(&kernel_mutex));
return(trx_sys_get_new_trx_id());
}
#endif /* !UNIV_HOTBACKUP */