1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-14 08:21:07 +03:00

Invent WAL timelines, as per recent discussion, to make point-in-time

recovery more manageable.  Also, undo recent change to add FILE_HEADER
and WASTED_SPACE records to XLOG; instead make the XLOG page header
variable-size with extra fields in the first page of an XLOG file.
This should fix the boundary-case bugs observed by Mark Kirkwood.
initdb forced due to change of XLOG representation.
This commit is contained in:
Tom Lane
2004-07-21 22:31:26 +00:00
parent 8d3517dc1f
commit 2042b3428d
26 changed files with 1322 additions and 982 deletions

View File

@ -2,169 +2,31 @@
*
* xlogutils.c
*
* PostgreSQL transaction log manager utility routines
*
* This file contains support routines that are used by XLOG replay functions.
* None of this code is used during normal system operation.
*
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.31 2004/06/18 06:13:15 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.32 2004/07/21 22:31:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/htup.h"
#include "access/xlogutils.h"
#include "catalog/pg_database.h"
#include "storage/bufpage.h"
#include "storage/bufmgr.h"
#include "storage/smgr.h"
#include "utils/hsearch.h"
#include "utils/relcache.h"
/*
* ---------------------------------------------------------------
*
* Index support functions
*
*----------------------------------------------------------------
*/
/*
* Check if specified heap tuple was inserted by given
* xaction/command and return
*
* - -1 if not
* - 0 if there is no tuple at all
* - 1 if yes
*/
int
XLogIsOwnerOfTuple(RelFileNode hnode, ItemPointer iptr,
TransactionId xid, CommandId cid)
{
Relation reln;
Buffer buffer;
Page page;
ItemId lp;
HeapTupleHeader htup;
reln = XLogOpenRelation(false, RM_HEAP_ID, hnode);
if (!RelationIsValid(reln))
return (0);
buffer = ReadBuffer(reln, ItemPointerGetBlockNumber(iptr));
if (!BufferIsValid(buffer))
return (0);
LockBuffer(buffer, BUFFER_LOCK_SHARE);
page = (Page) BufferGetPage(buffer);
if (PageIsNew((PageHeader) page) ||
ItemPointerGetOffsetNumber(iptr) > PageGetMaxOffsetNumber(page))
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
ReleaseBuffer(buffer);
return (0);
}
lp = PageGetItemId(page, ItemPointerGetOffsetNumber(iptr));
if (!ItemIdIsUsed(lp) || ItemIdDeleted(lp))
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
ReleaseBuffer(buffer);
return (0);
}
htup = (HeapTupleHeader) PageGetItem(page, lp);
Assert(PageGetSUI(page) == ThisStartUpID);
if (!TransactionIdEquals(HeapTupleHeaderGetXmin(htup), xid) ||
HeapTupleHeaderGetCmin(htup) != cid)
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
ReleaseBuffer(buffer);
return (-1);
}
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
ReleaseBuffer(buffer);
return (1);
}
/*
* MUST BE CALLED ONLY ON RECOVERY.
*
* Check if exists valid (inserted by not aborted xaction) heap tuple
* for given item pointer
*/
bool
XLogIsValidTuple(RelFileNode hnode, ItemPointer iptr)
{
Relation reln;
Buffer buffer;
Page page;
ItemId lp;
HeapTupleHeader htup;
reln = XLogOpenRelation(false, RM_HEAP_ID, hnode);
if (!RelationIsValid(reln))
return (false);
buffer = ReadBuffer(reln, ItemPointerGetBlockNumber(iptr));
if (!BufferIsValid(buffer))
return (false);
LockBuffer(buffer, BUFFER_LOCK_SHARE);
page = (Page) BufferGetPage(buffer);
if (PageIsNew((PageHeader) page) ||
ItemPointerGetOffsetNumber(iptr) > PageGetMaxOffsetNumber(page))
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
ReleaseBuffer(buffer);
return (false);
}
if (PageGetSUI(page) != ThisStartUpID)
{
Assert(PageGetSUI(page) < ThisStartUpID);
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
ReleaseBuffer(buffer);
return (true);
}
lp = PageGetItemId(page, ItemPointerGetOffsetNumber(iptr));
if (!ItemIdIsUsed(lp) || ItemIdDeleted(lp))
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
ReleaseBuffer(buffer);
return (false);
}
htup = (HeapTupleHeader) PageGetItem(page, lp);
/* MUST CHECK WASN'T TUPLE INSERTED IN PREV STARTUP */
if (!(htup->t_infomask & HEAP_XMIN_COMMITTED))
{
if (htup->t_infomask & HEAP_XMIN_INVALID ||
(htup->t_infomask & HEAP_MOVED_IN &&
TransactionIdDidAbort(HeapTupleHeaderGetXvac(htup))) ||
TransactionIdDidAbort(HeapTupleHeaderGetXmin(htup)))
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
ReleaseBuffer(buffer);
return (false);
}
}
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
ReleaseBuffer(buffer);
return (true);
}
/*
* ---------------------------------------------------------------
*
* Storage related support functions
*
*----------------------------------------------------------------
*/
Buffer
@ -198,8 +60,10 @@ XLogReadBuffer(bool extend, Relation reln, BlockNumber blkno)
return (buffer);
}
/*
* "Relation" cache
* Lightweight "Relation" cache --- this substitutes for the normal relcache
* during XLOG replay.
*/
typedef struct XLogRelDesc