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:
parent
8d3517dc1f
commit
2042b3428d
doc/src/sgml
src
backend
access
heap
nbtree
transam
commands
postmaster
storage/lmgr
bin
include
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/page.sgml,v 1.17 2003/12/14 00:10:32 neilc Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/page.sgml,v 1.18 2004/07/21 22:31:18 tgl Exp $
|
||||
-->
|
||||
|
||||
<chapter id="page">
|
||||
@ -114,37 +114,38 @@ data. Empty in ordinary tables.</entry>
|
||||
<entry>pd_lsn</entry>
|
||||
<entry>XLogRecPtr</entry>
|
||||
<entry>8 bytes</entry>
|
||||
<entry>LSN: next byte after last byte of xlog</entry>
|
||||
<entry>LSN: next byte after last byte of xlog record for last change
|
||||
to this page</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>pd_sui</entry>
|
||||
<entry>StartUpID</entry>
|
||||
<entry>pd_tli</entry>
|
||||
<entry>TimeLineID</entry>
|
||||
<entry>4 bytes</entry>
|
||||
<entry>SUI of last changes (currently it's used by heap AM only)</entry>
|
||||
<entry>TLI of last change</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>pd_lower</entry>
|
||||
<entry>LocationIndex</entry>
|
||||
<entry>2 bytes</entry>
|
||||
<entry>Offset to start of free space.</entry>
|
||||
<entry>Offset to start of free space</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>pd_upper</entry>
|
||||
<entry>LocationIndex</entry>
|
||||
<entry>2 bytes</entry>
|
||||
<entry>Offset to end of free space.</entry>
|
||||
<entry>Offset to end of free space</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>pd_special</entry>
|
||||
<entry>LocationIndex</entry>
|
||||
<entry>2 bytes</entry>
|
||||
<entry>Offset to start of special space.</entry>
|
||||
<entry>Offset to start of special space</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>pd_pagesize_version</entry>
|
||||
<entry>uint16</entry>
|
||||
<entry>2 bytes</entry>
|
||||
<entry>Page size and layout version number information.</entry>
|
||||
<entry>Page size and layout version number information</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.170 2004/07/11 18:01:44 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.171 2004/07/21 22:31:19 tgl Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@ -1214,7 +1214,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid)
|
||||
recptr = XLogInsert(RM_HEAP_ID, info, rdata);
|
||||
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1390,7 +1390,7 @@ l1:
|
||||
recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_DELETE, rdata);
|
||||
|
||||
PageSetLSN(dp, recptr);
|
||||
PageSetSUI(dp, ThisStartUpID);
|
||||
PageSetTLI(dp, ThisTimeLineID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1748,10 +1748,10 @@ l2:
|
||||
if (newbuf != buffer)
|
||||
{
|
||||
PageSetLSN(BufferGetPage(newbuf), recptr);
|
||||
PageSetSUI(BufferGetPage(newbuf), ThisStartUpID);
|
||||
PageSetTLI(BufferGetPage(newbuf), ThisTimeLineID);
|
||||
}
|
||||
PageSetLSN(BufferGetPage(buffer), recptr);
|
||||
PageSetSUI(BufferGetPage(buffer), ThisStartUpID);
|
||||
PageSetTLI(BufferGetPage(buffer), ThisTimeLineID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1902,7 +1902,7 @@ l3:
|
||||
* XLOG stuff: no logging is required as long as we have no
|
||||
* savepoints. For savepoints private log could be used...
|
||||
*/
|
||||
PageSetSUI(BufferGetPage(*buffer), ThisStartUpID);
|
||||
PageSetTLI(BufferGetPage(*buffer), ThisTimeLineID);
|
||||
|
||||
/* store transaction information of xact marking the tuple */
|
||||
tuple->t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
|
||||
@ -2184,7 +2184,7 @@ heap_xlog_clean(bool redo, XLogRecPtr lsn, XLogRecord *record)
|
||||
PageRepairFragmentation(page, NULL);
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID); /* prev sui */
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
}
|
||||
@ -2217,7 +2217,7 @@ heap_xlog_newpage(bool redo, XLogRecPtr lsn, XLogRecord *record)
|
||||
memcpy(page, (char *) xlrec + SizeOfHeapNewpage, BLCKSZ);
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
}
|
||||
@ -2283,7 +2283,7 @@ heap_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record)
|
||||
/* Make sure there is no forward chain link in t_ctid */
|
||||
htup->t_ctid = xlrec->target.tid;
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
return;
|
||||
@ -2368,7 +2368,7 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
|
||||
if (offnum == InvalidOffsetNumber)
|
||||
elog(PANIC, "heap_insert_redo: failed to add tuple");
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID); /* prev sui */
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
return;
|
||||
@ -2466,7 +2466,7 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move)
|
||||
if (samepage)
|
||||
goto newsame;
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
goto newt;
|
||||
@ -2564,7 +2564,7 @@ newsame:;
|
||||
if (offnum == InvalidOffsetNumber)
|
||||
elog(PANIC, "heap_update_redo: failed to add tuple");
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID); /* prev sui */
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
return;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.112 2004/04/21 18:24:25 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.113 2004/07/21 22:31:19 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -621,11 +621,11 @@ _bt_insertonpg(Relation rel,
|
||||
if (BufferIsValid(metabuf))
|
||||
{
|
||||
PageSetLSN(metapg, recptr);
|
||||
PageSetSUI(metapg, ThisStartUpID);
|
||||
PageSetTLI(metapg, ThisTimeLineID);
|
||||
}
|
||||
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
}
|
||||
|
||||
END_CRIT_SECTION();
|
||||
@ -903,13 +903,13 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
|
||||
recptr = XLogInsert(RM_BTREE_ID, xlinfo, rdata);
|
||||
|
||||
PageSetLSN(leftpage, recptr);
|
||||
PageSetSUI(leftpage, ThisStartUpID);
|
||||
PageSetTLI(leftpage, ThisTimeLineID);
|
||||
PageSetLSN(rightpage, recptr);
|
||||
PageSetSUI(rightpage, ThisStartUpID);
|
||||
PageSetTLI(rightpage, ThisTimeLineID);
|
||||
if (!P_RIGHTMOST(ropaque))
|
||||
{
|
||||
PageSetLSN(spage, recptr);
|
||||
PageSetSUI(spage, ThisStartUpID);
|
||||
PageSetTLI(spage, ThisTimeLineID);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1494,13 +1494,13 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
|
||||
recptr = XLogInsert(RM_BTREE_ID, XLOG_BTREE_NEWROOT, rdata);
|
||||
|
||||
PageSetLSN(rootpage, recptr);
|
||||
PageSetSUI(rootpage, ThisStartUpID);
|
||||
PageSetTLI(rootpage, ThisTimeLineID);
|
||||
PageSetLSN(metapg, recptr);
|
||||
PageSetSUI(metapg, ThisStartUpID);
|
||||
PageSetTLI(metapg, ThisTimeLineID);
|
||||
PageSetLSN(lpage, recptr);
|
||||
PageSetSUI(lpage, ThisStartUpID);
|
||||
PageSetTLI(lpage, ThisTimeLineID);
|
||||
PageSetLSN(rpage, recptr);
|
||||
PageSetSUI(rpage, ThisStartUpID);
|
||||
PageSetTLI(rpage, ThisTimeLineID);
|
||||
}
|
||||
|
||||
END_CRIT_SECTION();
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.76 2004/06/02 17:28:17 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.77 2004/07/21 22:31:20 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Postgres btree pages look like ordinary relation pages. The opaque
|
||||
@ -84,7 +84,7 @@ _bt_metapinit(Relation rel)
|
||||
rdata);
|
||||
|
||||
PageSetLSN(pg, recptr);
|
||||
PageSetSUI(pg, ThisStartUpID);
|
||||
PageSetTLI(pg, ThisTimeLineID);
|
||||
}
|
||||
|
||||
END_CRIT_SECTION();
|
||||
@ -249,9 +249,9 @@ _bt_getroot(Relation rel, int access)
|
||||
recptr = XLogInsert(RM_BTREE_ID, XLOG_BTREE_NEWROOT, &rdata);
|
||||
|
||||
PageSetLSN(rootpage, recptr);
|
||||
PageSetSUI(rootpage, ThisStartUpID);
|
||||
PageSetTLI(rootpage, ThisTimeLineID);
|
||||
PageSetLSN(metapg, recptr);
|
||||
PageSetSUI(metapg, ThisStartUpID);
|
||||
PageSetTLI(metapg, ThisTimeLineID);
|
||||
}
|
||||
|
||||
END_CRIT_SECTION();
|
||||
@ -686,7 +686,7 @@ _bt_delitems(Relation rel, Buffer buf,
|
||||
recptr = XLogInsert(RM_BTREE_ID, XLOG_BTREE_DELETE, rdata);
|
||||
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
}
|
||||
|
||||
END_CRIT_SECTION();
|
||||
@ -1080,22 +1080,22 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
|
||||
if (BufferIsValid(metabuf))
|
||||
{
|
||||
PageSetLSN(metapg, recptr);
|
||||
PageSetSUI(metapg, ThisStartUpID);
|
||||
PageSetTLI(metapg, ThisTimeLineID);
|
||||
}
|
||||
page = BufferGetPage(pbuf);
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
page = BufferGetPage(rbuf);
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
page = BufferGetPage(buf);
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
if (BufferIsValid(lbuf))
|
||||
{
|
||||
page = BufferGetPage(lbuf);
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.84 2004/07/19 02:47:03 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.85 2004/07/21 22:31:20 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -299,14 +299,14 @@ _bt_blwritepage(BTWriteState *wstate, Page page, BlockNumber blkno)
|
||||
recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_NEWPAGE, rdata);
|
||||
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
|
||||
END_CRIT_SECTION();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Leave the page LSN zero if not WAL-logged, but set SUI anyway */
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
/* Leave the page LSN zero if not WAL-logged, but set TLI anyway */
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.15 2004/07/11 18:01:45 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.16 2004/07/21 22:31:20 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -136,7 +136,7 @@ _bt_restore_meta(Relation reln, XLogRecPtr lsn,
|
||||
pageop->btpo_flags = BTP_META;
|
||||
|
||||
PageSetLSN(metapg, lsn);
|
||||
PageSetSUI(metapg, ThisStartUpID);
|
||||
PageSetTLI(metapg, ThisTimeLineID);
|
||||
LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(metabuf);
|
||||
}
|
||||
@ -197,7 +197,7 @@ btree_xlog_insert(bool redo, bool isleaf, bool ismeta,
|
||||
elog(PANIC, "btree_insert_redo: failed to add item");
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
}
|
||||
@ -281,7 +281,7 @@ btree_xlog_split(bool redo, bool onleft, bool isroot,
|
||||
xlrec->leftlen);
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
}
|
||||
@ -317,7 +317,7 @@ btree_xlog_split(bool redo, bool onleft, bool isroot,
|
||||
record->xl_len - SizeOfBtreeSplit - xlrec->leftlen);
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
}
|
||||
@ -353,7 +353,7 @@ btree_xlog_split(bool redo, bool onleft, bool isroot,
|
||||
pageop->btpo_prev = rightsib;
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
}
|
||||
@ -420,7 +420,7 @@ btree_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record)
|
||||
}
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
}
|
||||
@ -489,7 +489,7 @@ btree_xlog_delete_page(bool redo, bool ismeta,
|
||||
}
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
}
|
||||
@ -515,7 +515,7 @@ btree_xlog_delete_page(bool redo, bool ismeta,
|
||||
pageop->btpo_prev = leftsib;
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
}
|
||||
@ -543,7 +543,7 @@ btree_xlog_delete_page(bool redo, bool ismeta,
|
||||
pageop->btpo_next = rightsib;
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
}
|
||||
@ -569,7 +569,7 @@ btree_xlog_delete_page(bool redo, bool ismeta,
|
||||
pageop->btpo_flags = BTP_DELETED;
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
}
|
||||
@ -632,7 +632,7 @@ btree_xlog_newroot(bool redo, XLogRecPtr lsn, XLogRecord *record)
|
||||
record->xl_len - SizeOfBtreeNewroot);
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
|
||||
|
@ -63,4 +63,12 @@
|
||||
#
|
||||
#recovery_target_inclusive = 'true' # 'true' or 'false'
|
||||
#
|
||||
#
|
||||
# If you want to recover into a timeline other than the "main line" shown in
|
||||
# pg_control, specify the timeline number here, or write 'latest' to get
|
||||
# the latest branch for which there's a history file.
|
||||
#
|
||||
#recovery_target_timeline = '33' # number or 'latest'
|
||||
#
|
||||
#
|
||||
#---------------------------------------------------------------------------
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Resource managers definition
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.13 2004/07/01 00:49:42 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.14 2004/07/21 22:31:20 tgl Exp $
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
@ -14,12 +14,12 @@
|
||||
#include "access/rtree.h"
|
||||
#include "access/slru.h"
|
||||
#include "access/xact.h"
|
||||
#include "access/xlog.h"
|
||||
#include "access/xlog_internal.h"
|
||||
#include "storage/smgr.h"
|
||||
#include "commands/sequence.h"
|
||||
|
||||
|
||||
RmgrData RmgrTable[RM_MAX_ID + 1] = {
|
||||
const RmgrData RmgrTable[RM_MAX_ID + 1] = {
|
||||
{"XLOG", xlog_redo, xlog_undo, xlog_desc, NULL, NULL},
|
||||
{"Transaction", xact_redo, xact_undo, xact_desc, NULL, NULL},
|
||||
{"Storage", smgr_redo, smgr_undo, smgr_desc, NULL, NULL},
|
||||
|
@ -6,7 +6,7 @@
|
||||
* 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/slru.c,v 1.17 2004/07/01 00:49:42 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.18 2004/07/21 22:31:20 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -22,6 +22,7 @@
|
||||
#include "postmaster/bgwriter.h"
|
||||
#include "storage/fd.h"
|
||||
#include "storage/lwlock.h"
|
||||
#include "storage/shmem.h"
|
||||
#include "miscadmin.h"
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.113 2004/07/12 05:37:03 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.114 2004/07/21 22:31:21 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -279,7 +279,7 @@ DefineSequence(CreateSeqStmt *seq)
|
||||
recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG | XLOG_NO_TRAN, rdata);
|
||||
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
}
|
||||
|
||||
END_CRIT_SECTION();
|
||||
@ -354,7 +354,7 @@ AlterSequence(AlterSeqStmt *stmt)
|
||||
recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG | XLOG_NO_TRAN, rdata);
|
||||
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
}
|
||||
|
||||
END_CRIT_SECTION();
|
||||
@ -553,7 +553,7 @@ nextval(PG_FUNCTION_ARGS)
|
||||
recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG | XLOG_NO_TRAN, rdata);
|
||||
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
}
|
||||
|
||||
/* update on-disk data */
|
||||
@ -689,7 +689,7 @@ do_setval(RangeVar *sequence, int64 next, bool iscalled)
|
||||
recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG | XLOG_NO_TRAN, rdata);
|
||||
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
}
|
||||
|
||||
/* save info in sequence relation */
|
||||
@ -1091,7 +1091,7 @@ seq_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
elog(PANIC, "seq_redo: failed to add item to page");
|
||||
|
||||
PageSetLSN(page, lsn);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||
WriteBuffer(buffer);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.121 2004/07/19 02:47:06 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.122 2004/07/21 22:31:21 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -5448,7 +5448,7 @@ copy_relation_data(Relation rel, SMgrRelation dst)
|
||||
recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_NEWPAGE, rdata);
|
||||
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
|
||||
END_CRIT_SECTION();
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.283 2004/07/20 22:56:29 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.284 2004/07/21 22:31:21 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -2341,7 +2341,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
|
||||
|
||||
recptr = log_heap_clean(onerel, buf, unused, uncnt);
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2491,10 +2491,10 @@ move_chain_tuple(Relation rel,
|
||||
if (old_buf != dst_buf)
|
||||
{
|
||||
PageSetLSN(old_page, recptr);
|
||||
PageSetSUI(old_page, ThisStartUpID);
|
||||
PageSetTLI(old_page, ThisTimeLineID);
|
||||
}
|
||||
PageSetLSN(dst_page, recptr);
|
||||
PageSetSUI(dst_page, ThisStartUpID);
|
||||
PageSetTLI(dst_page, ThisTimeLineID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2611,9 +2611,9 @@ move_plain_tuple(Relation rel,
|
||||
dst_buf, &newtup);
|
||||
|
||||
PageSetLSN(old_page, recptr);
|
||||
PageSetSUI(old_page, ThisStartUpID);
|
||||
PageSetTLI(old_page, ThisTimeLineID);
|
||||
PageSetLSN(dst_page, recptr);
|
||||
PageSetSUI(dst_page, ThisStartUpID);
|
||||
PageSetTLI(dst_page, ThisTimeLineID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2807,7 +2807,7 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
|
||||
|
||||
recptr = log_heap_clean(onerel, buffer, unused, uncnt);
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -31,7 +31,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.42 2004/06/05 19:48:07 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.43 2004/07/21 22:31:21 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -532,7 +532,7 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
|
||||
|
||||
recptr = log_heap_clean(onerel, buffer, unused, uncnt);
|
||||
PageSetLSN(page, recptr);
|
||||
PageSetSUI(page, ThisStartUpID);
|
||||
PageSetTLI(page, ThisTimeLineID);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -19,7 +19,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.1 2004/07/19 02:47:08 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.2 2004/07/21 22:31:22 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -31,9 +31,10 @@
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "postmaster/pgarch.h"
|
||||
#include "access/xlog_internal.h"
|
||||
#include "libpq/pqsignal.h"
|
||||
#include "miscadmin.h"
|
||||
#include "postmaster/pgarch.h"
|
||||
#include "postmaster/postmaster.h"
|
||||
#include "storage/fd.h"
|
||||
#include "storage/ipc.h"
|
||||
@ -63,8 +64,8 @@
|
||||
* ----------
|
||||
*/
|
||||
#define MIN_XFN_CHARS 16
|
||||
#define MAX_XFN_CHARS 16
|
||||
#define VALID_XFN_CHARS "0123456789ABCDEF"
|
||||
#define MAX_XFN_CHARS 24
|
||||
#define VALID_XFN_CHARS "0123456789ABCDEF.history"
|
||||
|
||||
#define NUM_ARCHIVE_RETRIES 3
|
||||
|
||||
@ -73,8 +74,6 @@
|
||||
* Local data
|
||||
* ----------
|
||||
*/
|
||||
static char XLogDir[MAXPGPATH];
|
||||
static char XLogArchiveStatusDir[MAXPGPATH];
|
||||
static time_t last_pgarch_start_time;
|
||||
|
||||
/*
|
||||
@ -265,9 +264,8 @@ PgArchiverMain(int argc, char *argv[])
|
||||
init_ps_display("archiver process", "", "");
|
||||
set_ps_display("");
|
||||
|
||||
/* Init XLOG file paths */
|
||||
snprintf(XLogDir, MAXPGPATH, "%s/pg_xlog", DataDir);
|
||||
snprintf(XLogArchiveStatusDir, MAXPGPATH, "%s/archive_status", XLogDir);
|
||||
/* Init XLOG file paths --- needed in EXEC_BACKEND case */
|
||||
XLOGPathInit();
|
||||
|
||||
pgarch_MainLoop();
|
||||
|
||||
@ -497,6 +495,12 @@ pgarch_archiveXlog(char *xlog)
|
||||
* 1) to maintain the sequential chain of xlogs required for recovery
|
||||
* 2) because the oldest ones will sooner become candidates for
|
||||
* recycling at time of checkpoint
|
||||
*
|
||||
* NOTE: the "oldest" comparison will presently consider all segments of
|
||||
* a timeline with a smaller ID to be older than all segments of a timeline
|
||||
* with a larger ID; the net result being that past timelines are given
|
||||
* higher priority for archiving. This seems okay, or at least not
|
||||
* obviously worth changing.
|
||||
*/
|
||||
static bool
|
||||
pgarch_readyXlog(char *xlog)
|
||||
@ -507,11 +511,13 @@ pgarch_readyXlog(char *xlog)
|
||||
* It is possible to optimise this code, though only a single
|
||||
* file is expected on the vast majority of calls, so....
|
||||
*/
|
||||
char XLogArchiveStatusDir[MAXPGPATH];
|
||||
char newxlog[MAX_XFN_CHARS + 6 + 1];
|
||||
DIR *rldir;
|
||||
struct dirent *rlde;
|
||||
bool found = false;
|
||||
|
||||
snprintf(XLogArchiveStatusDir, MAXPGPATH, "%s/archive_status", XLogDir);
|
||||
rldir = AllocateDir(XLogArchiveStatusDir);
|
||||
if (rldir == NULL)
|
||||
ereport(ERROR,
|
||||
@ -575,14 +581,12 @@ pgarch_archiveDone(char *xlog)
|
||||
{
|
||||
char rlogready[MAXPGPATH];
|
||||
char rlogdone[MAXPGPATH];
|
||||
int rc;
|
||||
|
||||
snprintf(rlogready, MAXPGPATH, "%s/%s.ready", XLogArchiveStatusDir, xlog);
|
||||
snprintf(rlogdone, MAXPGPATH, "%s/%s.done", XLogArchiveStatusDir, xlog);
|
||||
rc = rename(rlogready, rlogdone);
|
||||
if (rc < 0)
|
||||
StatusFilePath(rlogready, xlog, ".ready");
|
||||
StatusFilePath(rlogdone, xlog, ".done");
|
||||
if (rename(rlogready, rlogdone) < 0)
|
||||
ereport(WARNING,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not rename \"%s\": %m",
|
||||
rlogready)));
|
||||
errmsg("could not rename \"%s\" to \"%s\": %m",
|
||||
rlogready, rlogdone)));
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.28 2004/06/05 19:48:08 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.29 2004/07/21 22:31:22 tgl Exp $
|
||||
*
|
||||
* Interface:
|
||||
*
|
||||
@ -25,6 +25,7 @@
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "catalog/pg_class.h"
|
||||
#include "lib/stringinfo.h"
|
||||
#include "miscadmin.h"
|
||||
#include "storage/proc.h"
|
||||
|
@ -6,7 +6,7 @@
|
||||
* copyright (c) Oliver Elphick <olly@lfix.co.uk>, 2001;
|
||||
* licence: BSD
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.17 2004/06/03 00:07:36 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/bin/pg_controldata/pg_controldata.c,v 1.18 2004/07/21 22:31:23 tgl Exp $
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
@ -165,7 +165,7 @@ main(int argc, char *argv[])
|
||||
ControlFile.checkPointCopy.redo.xlogid, ControlFile.checkPointCopy.redo.xrecoff);
|
||||
printf(_("Latest checkpoint's UNDO location: %X/%X\n"),
|
||||
ControlFile.checkPointCopy.undo.xlogid, ControlFile.checkPointCopy.undo.xrecoff);
|
||||
printf(_("Latest checkpoint's StartUpID: %u\n"), ControlFile.checkPointCopy.ThisStartUpID);
|
||||
printf(_("Latest checkpoint's TimeLineID: %u\n"), ControlFile.checkPointCopy.ThisTimeLineID);
|
||||
printf(_("Latest checkpoint's NextXID: %u\n"), ControlFile.checkPointCopy.nextXid);
|
||||
printf(_("Latest checkpoint's NextOID: %u\n"), ControlFile.checkPointCopy.nextOid);
|
||||
printf(_("Time of latest checkpoint: %s\n"), ckpttime_str);
|
||||
|
@ -23,22 +23,22 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.20 2004/06/03 00:07:37 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/bin/pg_resetxlog/pg_resetxlog.c,v 1.21 2004/07/21 22:31:24 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <locale.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "access/xlog.h"
|
||||
#include "access/xlog_internal.h"
|
||||
#include "catalog/catversion.h"
|
||||
#include "catalog/pg_control.h"
|
||||
|
||||
@ -48,27 +48,7 @@ extern char *optarg;
|
||||
#define _(x) gettext((x))
|
||||
|
||||
|
||||
/******************** stuff copied from xlog.c ********************/
|
||||
|
||||
/* Increment an xlogid/segment pair */
|
||||
#define NextLogSeg(logId, logSeg) \
|
||||
do { \
|
||||
if ((logSeg) >= XLogSegsPerFile-1) \
|
||||
{ \
|
||||
(logId)++; \
|
||||
(logSeg) = 0; \
|
||||
} \
|
||||
else \
|
||||
(logSeg)++; \
|
||||
} while (0)
|
||||
|
||||
#define XLogFileName(path, log, seg) \
|
||||
snprintf(path, MAXPGPATH, "%s/%08X%08X", \
|
||||
XLogDir, log, seg)
|
||||
|
||||
/******************** end of stuff copied from xlog.c ********************/
|
||||
|
||||
static char XLogDir[MAXPGPATH];
|
||||
char XLogDir[MAXPGPATH]; /* not static, see xlog_internal.h */
|
||||
static char ControlFilePath[MAXPGPATH];
|
||||
|
||||
static ControlFileData ControlFile; /* pg_control values */
|
||||
@ -388,9 +368,9 @@ GuessControlValues(void)
|
||||
ControlFile.system_identifier = sysidentifier;
|
||||
|
||||
ControlFile.checkPointCopy.redo.xlogid = 0;
|
||||
ControlFile.checkPointCopy.redo.xrecoff = SizeOfXLogPHD + SizeOfXLogRecord + SizeOfXLogFHD;
|
||||
ControlFile.checkPointCopy.redo.xrecoff = SizeOfXLogLongPHD;
|
||||
ControlFile.checkPointCopy.undo = ControlFile.checkPointCopy.redo;
|
||||
ControlFile.checkPointCopy.ThisStartUpID = 0;
|
||||
ControlFile.checkPointCopy.ThisTimeLineID = 1;
|
||||
ControlFile.checkPointCopy.nextXid = (TransactionId) 514; /* XXX */
|
||||
ControlFile.checkPointCopy.nextOid = BootstrapObjectIdData;
|
||||
ControlFile.checkPointCopy.time = time(NULL);
|
||||
@ -430,7 +410,7 @@ GuessControlValues(void)
|
||||
|
||||
/*
|
||||
* XXX eventually, should try to grovel through old XLOG to develop
|
||||
* more accurate values for startupid, nextXID, and nextOID.
|
||||
* more accurate values for TimeLineID, nextXID, and nextOID.
|
||||
*/
|
||||
}
|
||||
|
||||
@ -463,7 +443,7 @@ PrintControlValues(bool guessed)
|
||||
printf(_("Database system identifier: %s\n"), sysident_str);
|
||||
printf(_("Current log file ID: %u\n"), ControlFile.logId);
|
||||
printf(_("Next log file segment: %u\n"), ControlFile.logSeg);
|
||||
printf(_("Latest checkpoint's StartUpID: %u\n"), ControlFile.checkPointCopy.ThisStartUpID);
|
||||
printf(_("Latest checkpoint's TimeLineID: %u\n"), ControlFile.checkPointCopy.ThisTimeLineID);
|
||||
printf(_("Latest checkpoint's NextXID: %u\n"), ControlFile.checkPointCopy.nextXid);
|
||||
printf(_("Latest checkpoint's NextOID: %u\n"), ControlFile.checkPointCopy.nextOid);
|
||||
printf(_("Database block size: %u\n"), ControlFile.blcksz);
|
||||
@ -506,7 +486,7 @@ RewriteControlFile(void)
|
||||
|
||||
ControlFile.checkPointCopy.redo.xlogid = newXlogId;
|
||||
ControlFile.checkPointCopy.redo.xrecoff =
|
||||
newXlogSeg * XLogSegSize + SizeOfXLogPHD + SizeOfXLogRecord + SizeOfXLogFHD;
|
||||
newXlogSeg * XLogSegSize + SizeOfXLogLongPHD;
|
||||
ControlFile.checkPointCopy.undo = ControlFile.checkPointCopy.redo;
|
||||
ControlFile.checkPointCopy.time = time(NULL);
|
||||
|
||||
@ -634,8 +614,8 @@ WriteEmptyXLOG(void)
|
||||
{
|
||||
char *buffer;
|
||||
XLogPageHeader page;
|
||||
XLogLongPageHeader longpage;
|
||||
XLogRecord *record;
|
||||
XLogFileHeaderData *fhdr;
|
||||
crc64 crc;
|
||||
char path[MAXPGPATH];
|
||||
int fd;
|
||||
@ -648,41 +628,20 @@ WriteEmptyXLOG(void)
|
||||
|
||||
/* Set up the XLOG page header */
|
||||
page->xlp_magic = XLOG_PAGE_MAGIC;
|
||||
page->xlp_info = 0;
|
||||
page->xlp_sui = ControlFile.checkPointCopy.ThisStartUpID;
|
||||
page->xlp_info = XLP_LONG_HEADER;
|
||||
page->xlp_tli = ControlFile.checkPointCopy.ThisTimeLineID;
|
||||
page->xlp_pageaddr.xlogid =
|
||||
ControlFile.checkPointCopy.redo.xlogid;
|
||||
page->xlp_pageaddr.xrecoff =
|
||||
ControlFile.checkPointCopy.redo.xrecoff -
|
||||
(SizeOfXLogPHD + SizeOfXLogRecord + SizeOfXLogFHD);
|
||||
|
||||
/* Insert the file header record */
|
||||
record = (XLogRecord *) ((char *) page + SizeOfXLogPHD);
|
||||
record->xl_prev.xlogid = 0;
|
||||
record->xl_prev.xrecoff = 0;
|
||||
record->xl_xact_prev.xlogid = 0;
|
||||
record->xl_xact_prev.xrecoff = 0;
|
||||
record->xl_xid = InvalidTransactionId;
|
||||
record->xl_len = SizeOfXLogFHD;
|
||||
record->xl_info = XLOG_FILE_HEADER;
|
||||
record->xl_rmid = RM_XLOG_ID;
|
||||
fhdr = (XLogFileHeaderData *) XLogRecGetData(record);
|
||||
fhdr->xlfhd_sysid = ControlFile.system_identifier;
|
||||
fhdr->xlfhd_xlogid = page->xlp_pageaddr.xlogid;
|
||||
fhdr->xlfhd_segno = page->xlp_pageaddr.xrecoff / XLogSegSize;
|
||||
fhdr->xlfhd_seg_size = XLogSegSize;
|
||||
|
||||
INIT_CRC64(crc);
|
||||
COMP_CRC64(crc, fhdr, SizeOfXLogFHD);
|
||||
COMP_CRC64(crc, (char *) record + sizeof(crc64),
|
||||
SizeOfXLogRecord - sizeof(crc64));
|
||||
FIN_CRC64(crc);
|
||||
record->xl_crc = crc;
|
||||
ControlFile.checkPointCopy.redo.xrecoff - SizeOfXLogLongPHD;
|
||||
longpage = (XLogLongPageHeader) page;
|
||||
longpage->xlp_sysid = ControlFile.system_identifier;
|
||||
longpage->xlp_seg_size = XLogSegSize;
|
||||
|
||||
/* Insert the initial checkpoint record */
|
||||
record = (XLogRecord *) ((char *) page + SizeOfXLogPHD + SizeOfXLogRecord + SizeOfXLogFHD);
|
||||
record->xl_prev.xlogid = page->xlp_pageaddr.xlogid;
|
||||
record->xl_prev.xrecoff = page->xlp_pageaddr.xrecoff + SizeOfXLogPHD;
|
||||
record = (XLogRecord *) ((char *) page + SizeOfXLogLongPHD);
|
||||
record->xl_prev.xlogid = 0;
|
||||
record->xl_prev.xrecoff = 0;
|
||||
record->xl_xact_prev.xlogid = 0;
|
||||
record->xl_xact_prev.xrecoff = 0;
|
||||
record->xl_xid = InvalidTransactionId;
|
||||
@ -700,7 +659,8 @@ WriteEmptyXLOG(void)
|
||||
record->xl_crc = crc;
|
||||
|
||||
/* Write the first page */
|
||||
XLogFileName(path, newXlogId, newXlogSeg);
|
||||
XLogFilePath(path, ControlFile.checkPointCopy.ThisTimeLineID,
|
||||
newXlogId, newXlogSeg);
|
||||
|
||||
unlink(path);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/xact.h,v 1.65 2004/07/17 03:30:38 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/xact.h,v 1.66 2004/07/21 22:31:25 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -15,6 +15,7 @@
|
||||
#define XACT_H
|
||||
|
||||
#include "access/xlog.h"
|
||||
#include "storage/relfilenode.h"
|
||||
#include "utils/nabstime.h"
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.53 2004/07/19 02:47:13 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.54 2004/07/21 22:31:25 tgl Exp $
|
||||
*/
|
||||
#ifndef XLOG_H
|
||||
#define XLOG_H
|
||||
@ -14,7 +14,7 @@
|
||||
#include "access/rmgr.h"
|
||||
#include "access/transam.h"
|
||||
#include "access/xlogdefs.h"
|
||||
#include "storage/bufmgr.h"
|
||||
#include "storage/buf.h"
|
||||
#include "utils/pg_crc.h"
|
||||
|
||||
|
||||
@ -76,107 +76,6 @@ typedef struct XLogRecord
|
||||
#define XLOG_NO_TRAN XLR_INFO_MASK
|
||||
|
||||
/*
|
||||
* Header info for a backup block appended to an XLOG record.
|
||||
*
|
||||
* Note that the backup block has its own CRC, and is not covered by
|
||||
* the CRC of the XLOG record proper. Also note that we don't attempt
|
||||
* to align either the BkpBlock struct or the block's data.
|
||||
*/
|
||||
typedef struct BkpBlock
|
||||
{
|
||||
crc64 crc;
|
||||
RelFileNode node;
|
||||
BlockNumber block;
|
||||
} BkpBlock;
|
||||
|
||||
/*
|
||||
* When there is not enough space on current page for whole record, we
|
||||
* continue on the next page with continuation record. (However, the
|
||||
* XLogRecord header will never be split across pages; if there's less than
|
||||
* SizeOfXLogRecord space left at the end of a page, we just waste it.)
|
||||
*
|
||||
* Note that xl_rem_len includes backup-block data, unlike xl_len in the
|
||||
* initial header.
|
||||
*/
|
||||
typedef struct XLogContRecord
|
||||
{
|
||||
uint32 xl_rem_len; /* total len of remaining data for record */
|
||||
|
||||
/* ACTUAL LOG DATA FOLLOWS AT END OF STRUCT */
|
||||
|
||||
} XLogContRecord;
|
||||
|
||||
#define SizeOfXLogContRecord MAXALIGN(sizeof(XLogContRecord))
|
||||
|
||||
/*
|
||||
* Each page of XLOG file has a header like this:
|
||||
*/
|
||||
#define XLOG_PAGE_MAGIC 0xD05B /* can be used as WAL version indicator */
|
||||
|
||||
typedef struct XLogPageHeaderData
|
||||
{
|
||||
uint16 xlp_magic; /* magic value for correctness checks */
|
||||
uint16 xlp_info; /* flag bits, see below */
|
||||
StartUpID xlp_sui; /* StartUpID of first record on page */
|
||||
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
|
||||
} XLogPageHeaderData;
|
||||
|
||||
#define SizeOfXLogPHD MAXALIGN(sizeof(XLogPageHeaderData))
|
||||
|
||||
typedef XLogPageHeaderData *XLogPageHeader;
|
||||
|
||||
/* When record crosses page boundary, set this flag in new page's header */
|
||||
#define XLP_FIRST_IS_CONTRECORD 0x0001
|
||||
/* All defined flag bits in xlp_info (used for validity checking of header) */
|
||||
#define XLP_ALL_FLAGS 0x0001
|
||||
|
||||
/*
|
||||
* We break each logical log file (xlogid value) into segment files of the
|
||||
* size indicated by XLOG_SEG_SIZE. One possible segment at the end of each
|
||||
* log file is wasted, to ensure that we don't have problems representing
|
||||
* last-byte-position-plus-1.
|
||||
*/
|
||||
#define XLogSegSize ((uint32) XLOG_SEG_SIZE)
|
||||
#define XLogSegsPerFile (((uint32) 0xffffffff) / XLogSegSize)
|
||||
#define XLogFileSize (XLogSegsPerFile * XLogSegSize)
|
||||
|
||||
/*
|
||||
* The first XLOG record in each segment file is always an XLOG_FILE_HEADER
|
||||
* record. This record does nothing as far as XLOG replay is concerned,
|
||||
* but it is useful for verifying that we haven't mixed up XLOG segment files.
|
||||
* The body of an XLOG_FILE_HEADER record is a struct XLogFileHeaderData.
|
||||
* Note: the xlogid/segno fields are really redundant with xlp_pageaddr in
|
||||
* the page header, but we store them anyway as an extra check.
|
||||
*/
|
||||
typedef struct XLogFileHeaderData
|
||||
{
|
||||
uint64 xlfhd_sysid; /* system identifier from pg_control */
|
||||
uint32 xlfhd_xlogid; /* logical log file # */
|
||||
uint32 xlfhd_segno; /* segment number within logical log file */
|
||||
uint32 xlfhd_seg_size; /* just as a cross-check */
|
||||
} XLogFileHeaderData;
|
||||
|
||||
#define SizeOfXLogFHD MAXALIGN(sizeof(XLogFileHeaderData))
|
||||
|
||||
|
||||
/*
|
||||
* Method table for resource managers.
|
||||
*
|
||||
* RmgrTable[] is indexed by RmgrId values (see rmgr.h).
|
||||
*/
|
||||
typedef struct RmgrData
|
||||
{
|
||||
const char *rm_name;
|
||||
void (*rm_redo) (XLogRecPtr lsn, XLogRecord *rptr);
|
||||
void (*rm_undo) (XLogRecPtr lsn, XLogRecord *rptr);
|
||||
void (*rm_desc) (char *buf, uint8 xl_info, char *rec);
|
||||
void (*rm_startup) (void);
|
||||
void (*rm_cleanup) (void);
|
||||
} RmgrData;
|
||||
|
||||
extern RmgrData RmgrTable[];
|
||||
|
||||
/*--------------------
|
||||
* List of these structs is used to pass data to XLogInsert().
|
||||
*
|
||||
* If buffer is valid then XLOG will check if buffer must be backed up
|
||||
@ -188,7 +87,6 @@ extern RmgrData RmgrTable[];
|
||||
* the XLOG record, since we assume it's present in the buffer. Therefore,
|
||||
* rmgr redo routines MUST pay attention to XLR_BKP_BLOCK_X to know what
|
||||
* is actually stored in the XLOG record.
|
||||
*--------------------
|
||||
*/
|
||||
typedef struct XLogRecData
|
||||
{
|
||||
@ -198,7 +96,7 @@ typedef struct XLogRecData
|
||||
struct XLogRecData *next;
|
||||
} XLogRecData;
|
||||
|
||||
extern StartUpID ThisStartUpID; /* current SUI */
|
||||
extern TimeLineID ThisTimeLineID; /* current TLI */
|
||||
extern bool InRecovery;
|
||||
extern XLogRecPtr MyLastRecPtr;
|
||||
extern bool MyXactMadeXLogEntry;
|
||||
|
224
src/include/access/xlog_internal.h
Normal file
224
src/include/access/xlog_internal.h
Normal file
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* xlog_internal.h
|
||||
*
|
||||
* PostgreSQL transaction log internal declarations
|
||||
*
|
||||
* NOTE: this file is intended to contain declarations useful for
|
||||
* manipulating the XLOG files directly, but it is not supposed to be
|
||||
* needed by rmgr routines (redo/undo support for individual record types).
|
||||
* So the XLogRecord typedef and associated stuff appear in xlog.h.
|
||||
*
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.1 2004/07/21 22:31:25 tgl Exp $
|
||||
*/
|
||||
#ifndef XLOG_INTERNAL_H
|
||||
#define XLOG_INTERNAL_H
|
||||
|
||||
#include "access/xlog.h"
|
||||
#include "storage/block.h"
|
||||
#include "storage/relfilenode.h"
|
||||
|
||||
|
||||
/*
|
||||
* Header info for a backup block appended to an XLOG record.
|
||||
*
|
||||
* Note that the backup block has its own CRC, and is not covered by
|
||||
* the CRC of the XLOG record proper. Also note that we don't attempt
|
||||
* to align either the BkpBlock struct or the block's data.
|
||||
*/
|
||||
typedef struct BkpBlock
|
||||
{
|
||||
crc64 crc;
|
||||
RelFileNode node;
|
||||
BlockNumber block;
|
||||
} BkpBlock;
|
||||
|
||||
/*
|
||||
* When there is not enough space on current page for whole record, we
|
||||
* continue on the next page with continuation record. (However, the
|
||||
* XLogRecord header will never be split across pages; if there's less than
|
||||
* SizeOfXLogRecord space left at the end of a page, we just waste it.)
|
||||
*
|
||||
* Note that xl_rem_len includes backup-block data, unlike xl_len in the
|
||||
* initial header.
|
||||
*/
|
||||
typedef struct XLogContRecord
|
||||
{
|
||||
uint32 xl_rem_len; /* total len of remaining data for record */
|
||||
|
||||
/* ACTUAL LOG DATA FOLLOWS AT END OF STRUCT */
|
||||
|
||||
} XLogContRecord;
|
||||
|
||||
#define SizeOfXLogContRecord MAXALIGN(sizeof(XLogContRecord))
|
||||
|
||||
/*
|
||||
* Each page of XLOG file has a header like this:
|
||||
*/
|
||||
#define XLOG_PAGE_MAGIC 0xD05B /* can be used as WAL version indicator */
|
||||
|
||||
typedef struct XLogPageHeaderData
|
||||
{
|
||||
uint16 xlp_magic; /* magic value for correctness checks */
|
||||
uint16 xlp_info; /* flag bits, see below */
|
||||
TimeLineID xlp_tli; /* TimeLineID of first record on page */
|
||||
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
|
||||
} XLogPageHeaderData;
|
||||
|
||||
#define SizeOfXLogShortPHD MAXALIGN(sizeof(XLogPageHeaderData))
|
||||
|
||||
typedef XLogPageHeaderData *XLogPageHeader;
|
||||
|
||||
/*
|
||||
* When the XLP_LONG_HEADER flag is set, we store additional fields in the
|
||||
* page header. (This is ordinarily done just in the first page of an
|
||||
* XLOG file.) The additional fields serve to identify the file accurately.
|
||||
*/
|
||||
typedef struct XLogLongPageHeaderData
|
||||
{
|
||||
XLogPageHeaderData std; /* standard header fields */
|
||||
uint64 xlp_sysid; /* system identifier from pg_control */
|
||||
uint32 xlp_seg_size; /* just as a cross-check */
|
||||
} XLogLongPageHeaderData;
|
||||
|
||||
#define SizeOfXLogLongPHD MAXALIGN(sizeof(XLogLongPageHeaderData))
|
||||
|
||||
typedef XLogLongPageHeaderData *XLogLongPageHeader;
|
||||
|
||||
/* When record crosses page boundary, set this flag in new page's header */
|
||||
#define XLP_FIRST_IS_CONTRECORD 0x0001
|
||||
/* This flag indicates a "long" page header */
|
||||
#define XLP_LONG_HEADER 0x0002
|
||||
/* All defined flag bits in xlp_info (used for validity checking of header) */
|
||||
#define XLP_ALL_FLAGS 0x0003
|
||||
|
||||
#define XLogPageHeaderSize(hdr) \
|
||||
(((hdr)->xlp_info & XLP_LONG_HEADER) ? SizeOfXLogLongPHD : SizeOfXLogShortPHD)
|
||||
|
||||
/*
|
||||
* We break each logical log file (xlogid value) into segment files of the
|
||||
* size indicated by XLOG_SEG_SIZE. One possible segment at the end of each
|
||||
* log file is wasted, to ensure that we don't have problems representing
|
||||
* last-byte-position-plus-1.
|
||||
*/
|
||||
#define XLogSegSize ((uint32) XLOG_SEG_SIZE)
|
||||
#define XLogSegsPerFile (((uint32) 0xffffffff) / XLogSegSize)
|
||||
#define XLogFileSize (XLogSegsPerFile * XLogSegSize)
|
||||
|
||||
|
||||
/*
|
||||
* Macros for manipulating XLOG pointers
|
||||
*/
|
||||
|
||||
/* Increment an xlogid/segment pair */
|
||||
#define NextLogSeg(logId, logSeg) \
|
||||
do { \
|
||||
if ((logSeg) >= XLogSegsPerFile-1) \
|
||||
{ \
|
||||
(logId)++; \
|
||||
(logSeg) = 0; \
|
||||
} \
|
||||
else \
|
||||
(logSeg)++; \
|
||||
} while (0)
|
||||
|
||||
/* Decrement an xlogid/segment pair (assume it's not 0,0) */
|
||||
#define PrevLogSeg(logId, logSeg) \
|
||||
do { \
|
||||
if (logSeg) \
|
||||
(logSeg)--; \
|
||||
else \
|
||||
{ \
|
||||
(logId)--; \
|
||||
(logSeg) = XLogSegsPerFile-1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Compute ID and segment from an XLogRecPtr.
|
||||
*
|
||||
* For XLByteToSeg, do the computation at face value. For XLByteToPrevSeg,
|
||||
* a boundary byte is taken to be in the previous segment. This is suitable
|
||||
* for deciding which segment to write given a pointer to a record end,
|
||||
* for example. (We can assume xrecoff is not zero, since no valid recptr
|
||||
* can have that.)
|
||||
*/
|
||||
#define XLByteToSeg(xlrp, logId, logSeg) \
|
||||
( logId = (xlrp).xlogid, \
|
||||
logSeg = (xlrp).xrecoff / XLogSegSize \
|
||||
)
|
||||
#define XLByteToPrevSeg(xlrp, logId, logSeg) \
|
||||
( logId = (xlrp).xlogid, \
|
||||
logSeg = ((xlrp).xrecoff - 1) / XLogSegSize \
|
||||
)
|
||||
|
||||
/*
|
||||
* Is an XLogRecPtr within a particular XLOG segment?
|
||||
*
|
||||
* For XLByteInSeg, do the computation at face value. For XLByteInPrevSeg,
|
||||
* a boundary byte is taken to be in the previous segment.
|
||||
*/
|
||||
#define XLByteInSeg(xlrp, logId, logSeg) \
|
||||
((xlrp).xlogid == (logId) && \
|
||||
(xlrp).xrecoff / XLogSegSize == (logSeg))
|
||||
|
||||
#define XLByteInPrevSeg(xlrp, logId, logSeg) \
|
||||
((xlrp).xlogid == (logId) && \
|
||||
((xlrp).xrecoff - 1) / XLogSegSize == (logSeg))
|
||||
|
||||
/* Check if an xrecoff value is in a plausible range */
|
||||
#define XRecOffIsValid(xrecoff) \
|
||||
((xrecoff) % BLCKSZ >= SizeOfXLogShortPHD && \
|
||||
(BLCKSZ - (xrecoff) % BLCKSZ) >= SizeOfXLogRecord)
|
||||
|
||||
/*
|
||||
* These macros encapsulate knowledge about the exact layout of XLog file
|
||||
* names, timeline history file names, and archive-status file names.
|
||||
*/
|
||||
#define MAXFNAMELEN 32
|
||||
|
||||
#define XLogFileName(fname, tli, log, seg) \
|
||||
snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli, log, seg)
|
||||
|
||||
#define XLogFilePath(path, tli, log, seg) \
|
||||
snprintf(path, MAXPGPATH, "%s/%08X%08X%08X", XLogDir, tli, log, seg)
|
||||
|
||||
#define TLHistoryFileName(fname, tli) \
|
||||
snprintf(fname, MAXFNAMELEN, "%08X.history", tli)
|
||||
|
||||
#define TLHistoryFilePath(path, tli) \
|
||||
snprintf(path, MAXPGPATH, "%s/%08X.history", XLogDir, tli)
|
||||
|
||||
#define StatusFilePath(path, xlog, suffix) \
|
||||
snprintf(path, MAXPGPATH, "%s/archive_status/%s%s", XLogDir, xlog, suffix)
|
||||
|
||||
extern char XLogDir[MAXPGPATH];
|
||||
|
||||
/*
|
||||
* _INTL_MAXLOGRECSZ: max space needed for a record including header and
|
||||
* any backup-block data.
|
||||
*/
|
||||
#define _INTL_MAXLOGRECSZ (SizeOfXLogRecord + MAXLOGRECSZ + \
|
||||
XLR_MAX_BKP_BLOCKS * (sizeof(BkpBlock) + BLCKSZ))
|
||||
|
||||
|
||||
/*
|
||||
* Method table for resource managers.
|
||||
*
|
||||
* RmgrTable[] is indexed by RmgrId values (see rmgr.h).
|
||||
*/
|
||||
typedef struct RmgrData
|
||||
{
|
||||
const char *rm_name;
|
||||
void (*rm_redo) (XLogRecPtr lsn, XLogRecord *rptr);
|
||||
void (*rm_undo) (XLogRecPtr lsn, XLogRecord *rptr);
|
||||
void (*rm_desc) (char *buf, uint8 xl_info, char *rec);
|
||||
void (*rm_startup) (void);
|
||||
void (*rm_cleanup) (void);
|
||||
} RmgrData;
|
||||
|
||||
extern const RmgrData RmgrTable[];
|
||||
|
||||
#endif /* XLOG_INTERNAL_H */
|
@ -2,12 +2,12 @@
|
||||
* xlogdefs.h
|
||||
*
|
||||
* Postgres transaction log manager record pointer and
|
||||
* system startup number definitions
|
||||
* timeline number definitions
|
||||
*
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/xlogdefs.h,v 1.11 2003/12/20 17:31:21 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/xlogdefs.h,v 1.12 2004/07/21 22:31:25 tgl Exp $
|
||||
*/
|
||||
#ifndef XLOG_DEFS_H
|
||||
#define XLOG_DEFS_H
|
||||
@ -33,12 +33,6 @@ typedef struct XLogRecPtr
|
||||
uint32 xrecoff; /* byte offset of location in log file */
|
||||
} XLogRecPtr;
|
||||
|
||||
typedef struct XLogwrtResult
|
||||
{
|
||||
XLogRecPtr Write; /* last byte + 1 written out */
|
||||
XLogRecPtr Flush; /* last byte + 1 flushed */
|
||||
} XLogwrtResult;
|
||||
|
||||
|
||||
/*
|
||||
* Macros for comparing XLogRecPtrs
|
||||
@ -57,10 +51,16 @@ typedef struct XLogwrtResult
|
||||
#define XLByteEQ(a, b) \
|
||||
((a).xlogid == (b).xlogid && (a).xrecoff == (b).xrecoff)
|
||||
|
||||
|
||||
/*
|
||||
* StartUpID (SUI) - system startups counter. It's to allow removing
|
||||
* pg_clog after shutdown, in future.
|
||||
* TimeLineID (TLI) - identifies different database histories to prevent
|
||||
* confusion after restoring a prior state of a database installation.
|
||||
* TLI does not change in a normal stop/restart of the database (including
|
||||
* crash-and-recover cases); but we must assign a new TLI after doing
|
||||
* a recovery to a prior state, a/k/a point-in-time recovery. This makes
|
||||
* the new WAL logfile sequence we generate distinguishable from the
|
||||
* sequence that was generated in the previous incarnation.
|
||||
*/
|
||||
typedef uint32 StartUpID;
|
||||
typedef uint32 TimeLineID;
|
||||
|
||||
#endif /* XLOG_DEFS_H */
|
||||
|
@ -6,19 +6,15 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/access/xlogutils.h,v 1.14 2004/02/11 22:55:25 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/access/xlogutils.h,v 1.15 2004/07/21 22:31:25 tgl Exp $
|
||||
*/
|
||||
#ifndef XLOG_UTILS_H
|
||||
#define XLOG_UTILS_H
|
||||
|
||||
#include "access/rmgr.h"
|
||||
#include "storage/buf.h"
|
||||
#include "storage/itemptr.h"
|
||||
#include "utils/rel.h"
|
||||
|
||||
extern int XLogIsOwnerOfTuple(RelFileNode hnode, ItemPointer iptr,
|
||||
TransactionId xid, CommandId cid);
|
||||
extern bool XLogIsValidTuple(RelFileNode hnode, ItemPointer iptr);
|
||||
|
||||
extern void XLogInitRelationCache(void);
|
||||
extern void XLogCloseRelationCache(void);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.15 2004/06/03 02:08:05 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.16 2004/07/21 22:31:25 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
|
||||
/* Version identifier for this pg_control format */
|
||||
#define PG_CONTROL_VERSION 73
|
||||
#define PG_CONTROL_VERSION 74
|
||||
|
||||
/*
|
||||
* Body of CheckPoint XLOG records. This is declared here because we keep
|
||||
@ -30,13 +30,13 @@
|
||||
*/
|
||||
typedef struct CheckPoint
|
||||
{
|
||||
XLogRecPtr redo; /* next RecPtr available when we */
|
||||
/* began to create CheckPoint */
|
||||
/* (i.e. REDO start point) */
|
||||
XLogRecPtr undo; /* first record of oldest in-progress */
|
||||
/* transaction when we started */
|
||||
/* (i.e. UNDO end point) */
|
||||
StartUpID ThisStartUpID; /* current SUI */
|
||||
XLogRecPtr redo; /* next RecPtr available when we
|
||||
* began to create CheckPoint
|
||||
* (i.e. REDO start point) */
|
||||
XLogRecPtr undo; /* first record of oldest in-progress
|
||||
* transaction when we started
|
||||
* (i.e. UNDO end point) */
|
||||
TimeLineID ThisTimeLineID; /* current TLI */
|
||||
TransactionId nextXid; /* next free XID */
|
||||
Oid nextOid; /* next free OID */
|
||||
time_t time; /* time stamp of checkpoint */
|
||||
@ -46,8 +46,6 @@ typedef struct CheckPoint
|
||||
#define XLOG_CHECKPOINT_SHUTDOWN 0x00
|
||||
#define XLOG_CHECKPOINT_ONLINE 0x10
|
||||
#define XLOG_NEXTOID 0x30
|
||||
#define XLOG_FILE_HEADER 0x40
|
||||
#define XLOG_WASTED_SPACE 0x50
|
||||
|
||||
|
||||
/* System status indicator */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/storage/bufpage.h,v 1.59 2004/07/01 00:51:43 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/storage/bufpage.h,v 1.60 2004/07/21 22:31:26 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -87,13 +87,22 @@ typedef uint16 LocationIndex;
|
||||
|
||||
/*
|
||||
* disk page organization
|
||||
*
|
||||
* space management information generic to any page
|
||||
*
|
||||
* pd_lsn - identifies xlog record for last change to this page.
|
||||
* pd_tli - ditto.
|
||||
* pd_lower - offset to start of free space.
|
||||
* pd_upper - offset to end of free space.
|
||||
* pd_special - offset to start of special space.
|
||||
* pd_pagesize_version - size in bytes and page layout version number.
|
||||
*
|
||||
* The LSN is used by the buffer manager to enforce the basic rule of WAL:
|
||||
* "thou shalt write xlog before data". A dirty buffer cannot be dumped
|
||||
* to disk until xlog has been flushed at least as far as the page's LSN.
|
||||
* We also store the TLI for identification purposes (it is not clear that
|
||||
* this is actually necessary, but it seems like a good idea).
|
||||
*
|
||||
* The page version number and page size are packed together into a single
|
||||
* uint16 field. This is for historical reasons: before PostgreSQL 7.3,
|
||||
* there was no concept of a page version number, and doing it this way
|
||||
@ -109,13 +118,10 @@ typedef uint16 LocationIndex;
|
||||
*/
|
||||
typedef struct PageHeaderData
|
||||
{
|
||||
/* XXX LSN is member of *any* block, not */
|
||||
/* only page-organized - 'll change later */
|
||||
XLogRecPtr pd_lsn; /* LSN: next byte after last byte of xlog */
|
||||
/* record for last change of this page */
|
||||
StartUpID pd_sui; /* SUI of last changes (currently it's */
|
||||
/* used by heap AM only) */
|
||||
|
||||
/* XXX LSN is member of *any* block, not only page-organized ones */
|
||||
XLogRecPtr pd_lsn; /* LSN: next byte after last byte of xlog
|
||||
* record for last change to this page */
|
||||
TimeLineID pd_tli; /* TLI of last change */
|
||||
LocationIndex pd_lower; /* offset to start of free space */
|
||||
LocationIndex pd_upper; /* offset to end of free space */
|
||||
LocationIndex pd_special; /* offset to start of special space */
|
||||
@ -298,10 +304,10 @@ typedef PageHeaderData *PageHeader;
|
||||
#define PageSetLSN(page, lsn) \
|
||||
(((PageHeader) (page))->pd_lsn = (lsn))
|
||||
|
||||
#define PageGetSUI(page) \
|
||||
(((PageHeader) (page))->pd_sui)
|
||||
#define PageSetSUI(page, sui) \
|
||||
(((PageHeader) (page))->pd_sui = (StartUpID) (sui))
|
||||
#define PageGetTLI(page) \
|
||||
(((PageHeader) (page))->pd_tli)
|
||||
#define PageSetTLI(page, tli) \
|
||||
(((PageHeader) (page))->pd_tli = (tli))
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* extern declarations
|
||||
|
Loading…
x
Reference in New Issue
Block a user