/******************************************************
Mini-transaction buffer

(c) 1995 Innobase Oy

Created 11/26/1995 Heikki Tuuri
*******************************************************/

#ifndef mtr0mtr_h
#define mtr0mtr_h

#include "univ.i"
#include "mem0mem.h"
#include "dyn0dyn.h"
#include "buf0types.h"
#include "sync0rw.h"
#include "ut0byte.h"
#include "mtr0types.h"
#include "page0types.h"

/* Logging modes for a mini-transaction */
#define MTR_LOG_ALL		21	/* default mode: log all operations
					modifying disk-based data */
#define	MTR_LOG_NONE		22	/* log no operations */
/*#define	MTR_LOG_SPACE	23 */	/* log only operations modifying
					file space page allocation data
					(operations in fsp0fsp.* ) */
#define	MTR_LOG_SHORT_INSERTS	24	/* inserts are logged in a shorter
					form */
					
/* Types for the mlock objects to store in the mtr memo; NOTE that the
first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
#define	MTR_MEMO_PAGE_S_FIX	RW_S_LATCH
#define	MTR_MEMO_PAGE_X_FIX	RW_X_LATCH
#define	MTR_MEMO_BUF_FIX	RW_NO_LATCH
#define MTR_MEMO_MODIFY		54
#define	MTR_MEMO_S_LOCK		55
#define	MTR_MEMO_X_LOCK		56

/* Log item types: we have made them to be of the type 'byte'
for the compiler to warn if val and type parameters are switched
in a call to mlog_write_ulint. NOTE! For 1 - 8 bytes, the
flag value must give the length also! */
#define	MLOG_SINGLE_REC_FLAG	128		/* if the mtr contains only
						one log record for one page,
						i.e., write_initial_log_record
						has been called only once,
						this flag is ORed to the type
						of that first log record */
#define	MLOG_1BYTE		((byte)1) 	/* one byte is written */
#define	MLOG_2BYTES		((byte)2)	/* 2 bytes ... */
#define	MLOG_4BYTES		((byte)4)	/* 4 bytes ... */
#define	MLOG_8BYTES		((byte)8)	/* 8 bytes ... */
#define	MLOG_REC_INSERT		((byte)9)	/* record insert */
#define	MLOG_REC_CLUST_DELETE_MARK ((byte)10) 	/* mark clustered index record
						deleted */
#define	MLOG_REC_SEC_DELETE_MARK ((byte)11) 	/* mark secondary index record
						deleted */
#define MLOG_REC_UPDATE_IN_PLACE ((byte)13)	/* update of a record,
						preserves record field sizes */
#define MLOG_REC_DELETE		((byte)14)	/* delete a record from a
						page */
#define	MLOG_LIST_END_DELETE 	((byte)15)	/* delete record list end on
						index page */
#define	MLOG_LIST_START_DELETE 	((byte)16) 	/* delete record list start on
						index page */
#define	MLOG_LIST_END_COPY_CREATED ((byte)17) 	/* copy record list end to a
						new created index page */
#define	MLOG_PAGE_REORGANIZE 	((byte)18)	/* reorganize an index page */
#define MLOG_PAGE_CREATE 	((byte)19)	/* create an index page */
#define	MLOG_UNDO_INSERT 	((byte)20)	/* insert entry in an undo
						log */
#define MLOG_UNDO_ERASE_END	((byte)21)	/* erase an undo log page end */
#define	MLOG_UNDO_INIT 		((byte)22)	/* initialize a page in an
						undo log */
#define MLOG_UNDO_HDR_DISCARD	((byte)23)	/* discard an update undo log
						header */
#define	MLOG_UNDO_HDR_REUSE	((byte)24)	/* reuse an insert undo log
						header */
#define MLOG_UNDO_HDR_CREATE	((byte)25)	/* create an undo log header */
#define MLOG_REC_MIN_MARK	((byte)26)	/* mark an index record as the
						predefined minimum record */
#define MLOG_IBUF_BITMAP_INIT	((byte)27)	/* initialize an ibuf bitmap
						page */
/*#define	MLOG_FULL_PAGE	((byte)28)	full contents of a page */
#define MLOG_INIT_FILE_PAGE	((byte)29)	/* this means that a file page
						is taken into use and the prior
						contents of the page should be
						ignored: in recovery we must
						not trust the lsn values stored
						to the file page */
#define MLOG_WRITE_STRING	((byte)30)	/* write a string to a page */
#define	MLOG_MULTI_REC_END	((byte)31)	/* if a single mtr writes
						log records for several pages,
						this log record ends the
						sequence of these records */
#define MLOG_DUMMY_RECORD	((byte)32)	/* dummy log record used to
						pad a log block full */
#define MLOG_BIGGEST_TYPE	((byte)32) 	/* biggest value (used in
						asserts) */
					
/*******************************************************************
Starts a mini-transaction and creates a mini-transaction handle 
and buffer in the memory buffer given by the caller. */
UNIV_INLINE
mtr_t*
mtr_start(
/*======*/
			/* out: mtr buffer which also acts as
			the mtr handle */
	mtr_t*	mtr);	/* in: memory buffer for the mtr buffer */
/*******************************************************************
Starts a mini-transaction and creates a mini-transaction handle 
and buffer in the memory buffer given by the caller. */

mtr_t*
mtr_start_noninline(
/*================*/
			/* out: mtr buffer which also acts as
			the mtr handle */
	mtr_t*	mtr);	/* in: memory buffer for the mtr buffer */
/*******************************************************************
Commits a mini-transaction. */

void
mtr_commit(
/*=======*/
	mtr_t*	mtr);	/* in: mini-transaction */
/**************************************************************
Sets and returns a savepoint in mtr. */
UNIV_INLINE
ulint
mtr_set_savepoint(
/*==============*/
			/* out: savepoint */
	mtr_t*	mtr);	/* in: mtr */
/**************************************************************
Releases the latches stored in an mtr memo down to a savepoint.
NOTE! The mtr must not have made changes to buffer pages after the
savepoint, as these can be handled only by mtr_commit. */

void
mtr_rollback_to_savepoint(
/*======================*/
	mtr_t*	mtr,		/* in: mtr */
	ulint	savepoint);	/* in: savepoint */
/**************************************************************
Releases the (index tree) s-latch stored in an mtr memo after a
savepoint. */
UNIV_INLINE
void
mtr_release_s_latch_at_savepoint(
/*=============================*/
	mtr_t*		mtr,		/* in: mtr */
	ulint		savepoint,	/* in: savepoint */
	rw_lock_t* 	lock);		/* in: latch to release */
/*******************************************************************
Gets the logging mode of a mini-transaction. */
UNIV_INLINE
ulint
mtr_get_log_mode(
/*=============*/
			/* out: logging mode: MTR_LOG_NONE, ... */
	mtr_t*	mtr);	/* in: mtr */
/*******************************************************************
Changes the logging mode of a mini-transaction. */
UNIV_INLINE
ulint
mtr_set_log_mode(
/*=============*/
			/* out: old mode */
	mtr_t*	mtr,	/* in: mtr */
	ulint	mode);	/* in: logging mode: MTR_LOG_NONE, ... */
/************************************************************
Reads 1 - 4 bytes from a file page buffered in the buffer pool. */

ulint
mtr_read_ulint(
/*===========*/
			/* out: value read */
	byte*	ptr,	/* in: pointer from where to read */
	ulint	type,	/* in: MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES */
	mtr_t*	mtr);	/* in: mini-transaction handle */
/************************************************************
Reads 8 bytes from a file page buffered in the buffer pool. */

dulint
mtr_read_dulint(
/*===========*/
			/* out: value read */
	byte*	ptr,	/* in: pointer from where to read */
	mtr_t*	mtr);	/* in: mini-transaction handle */
/*************************************************************************
This macro locks an rw-lock in s-mode. */
#define mtr_s_lock(B, MTR)	mtr_s_lock_func((B), IB__FILE__, __LINE__,\
						(MTR))
/*************************************************************************
This macro locks an rw-lock in x-mode. */
#define mtr_x_lock(B, MTR)	mtr_x_lock_func((B), IB__FILE__, __LINE__,\
						(MTR))
/*************************************************************************
NOTE! Use the macro above!
Locks a lock in s-mode. */
UNIV_INLINE
void
mtr_s_lock_func(
/*============*/
	rw_lock_t*	lock,	/* in: rw-lock */
	char*		file,	/* in: file name */
	ulint		line,	/* in: line number */
	mtr_t*		mtr);	/* in: mtr */
/*************************************************************************
NOTE! Use the macro above!
Locks a lock in x-mode. */
UNIV_INLINE
void
mtr_x_lock_func(
/*============*/
	rw_lock_t*	lock,	/* in: rw-lock */
	char*		file,	/* in: file name */
	ulint		line,	/* in: line number */
	mtr_t*		mtr);	/* in: mtr */

/*******************************************************
Releases an object in the memo stack. */

void
mtr_memo_release(
/*=============*/
	mtr_t*	mtr,	/* in: mtr */
	void*	object,	/* in: object */
	ulint	type);	/* in: object type: MTR_MEMO_S_LOCK, ... */
/**************************************************************
Checks if memo contains the given item. */
UNIV_INLINE
ibool
mtr_memo_contains(
/*==============*/
			/* out: TRUE if contains */
	mtr_t*	mtr,	/* in: mtr */
	void*	object,	/* in: object to search */
	ulint	type);	/* in: type of object */
/*************************************************************
Prints info of an mtr handle. */

void
mtr_print(
/*======*/
	mtr_t*	mtr);	/* in: mtr */
/*######################################################################*/

#define	MTR_BUF_MEMO_SIZE	200	/* number of slots in memo */

/*******************************************************************
Returns the log object of a mini-transaction buffer. */
UNIV_INLINE
dyn_array_t*
mtr_get_log(
/*========*/
			/* out: log */
	mtr_t*	mtr);	/* in: mini-transaction */
/*******************************************************
Pushes an object to an mtr memo stack. */
UNIV_INLINE
void
mtr_memo_push(
/*==========*/
	mtr_t*	mtr,	/* in: mtr */
	void*	object,	/* in: object */
	ulint	type);	/* in: object type: MTR_MEMO_S_LOCK, ... */


/* Type definition of a mini-transaction memo stack slot. */
typedef	struct mtr_memo_slot_struct	mtr_memo_slot_t;
struct mtr_memo_slot_struct{
	ulint	type;	/* type of the stored object (MTR_MEMO_S_LOCK, ...) */
	void*	object;	/* pointer to the object */
};

/* Mini-transaction handle and buffer */
struct mtr_struct{
	ulint		state;	/* MTR_ACTIVE, MTR_COMMITTING, MTR_COMMITTED */
	dyn_array_t	memo;	/* memo stack for locks etc. */
	dyn_array_t	log;	/* mini-transaction log */
	ibool		modifications;
				/* TRUE if the mtr made modifications to
				buffer pool pages */
	ulint		n_log_recs;
				/* count of how many page initial log records
				have been written to the mtr log */
	ulint		log_mode; /* specifies which operations should be
				logged; default value MTR_LOG_ALL */
	dulint		start_lsn;/* start lsn of the possible log entry for
				this mtr */
	dulint		end_lsn;/* end lsn of the possible log entry for
				this mtr */
	ulint		magic_n;
};

#define	MTR_MAGIC_N		54551

#define MTR_ACTIVE		12231
#define MTR_COMMITTING		56456
#define MTR_COMMITTED		34676
	
#ifndef UNIV_NONINL
#include "mtr0mtr.ic"
#endif

#endif
