aboutsummaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorSimon Riggs <simon@2ndQuadrant.com>2009-12-19 01:32:45 +0000
committerSimon Riggs <simon@2ndQuadrant.com>2009-12-19 01:32:45 +0000
commitefc16ea520679d713d98a2c7bf1453c4ff7b91ec (patch)
tree6a39d2af0704a36281dc7df3ec10823eb3e6de75 /src/include
parent78a09145e0f8322e625bbc7d69fcb865ce4f3034 (diff)
downloadpostgresql-efc16ea520679d713d98a2c7bf1453c4ff7b91ec.tar.gz
postgresql-efc16ea520679d713d98a2c7bf1453c4ff7b91ec.zip
Allow read only connections during recovery, known as Hot Standby.
Enabled by recovery_connections = on (default) and forcing archive recovery using a recovery.conf. Recovery processing now emulates the original transactions as they are replayed, providing full locking and MVCC behaviour for read only queries. Recovery must enter consistent state before connections are allowed, so there is a delay, typically short, before connections succeed. Replay of recovering transactions can conflict and in some cases deadlock with queries during recovery; these result in query cancellation after max_standby_delay seconds have expired. Infrastructure changes have minor effects on normal running, though introduce four new types of WAL record. New test mode "make standbycheck" allows regression tests of static command behaviour on a standby server while in recovery. Typical and extreme dynamic behaviours have been checked via code inspection and manual testing. Few port specific behaviours have been utilised, though primary testing has been on Linux only so far. This commit is the basic patch. Additional changes will follow in this release to enhance some aspects of behaviour, notably improved handling of conflicts, deadlock detection and query cancellation. Changes to VACUUM FULL are also required. Simon Riggs, with significant and lengthy review by Heikki Linnakangas, including streamlined redesign of snapshot creation and two-phase commit. Important contributions from Florian Pflug, Mark Kirkwood, Merlin Moncure, Greg Stark, Gianni Ciolli, Gabriele Bartolini, Hannu Krosing, Robert Haas, Tatsuo Ishii, Hiroyuki Yamada plus support and feedback from many other community members.
Diffstat (limited to 'src/include')
-rw-r--r--src/include/access/heapam.h6
-rw-r--r--src/include/access/htup.h20
-rw-r--r--src/include/access/nbtree.h49
-rw-r--r--src/include/access/relscan.h3
-rw-r--r--src/include/access/rmgr.h3
-rw-r--r--src/include/access/subtrans.h4
-rw-r--r--src/include/access/transam.h5
-rw-r--r--src/include/access/twophase.h6
-rw-r--r--src/include/access/twophase_rmgr.h10
-rw-r--r--src/include/access/xact.h35
-rw-r--r--src/include/access/xlog.h44
-rw-r--r--src/include/access/xlog_internal.h5
-rw-r--r--src/include/catalog/pg_control.h16
-rw-r--r--src/include/catalog/pg_proc.h5
-rw-r--r--src/include/miscadmin.h8
-rw-r--r--src/include/storage/lock.h20
-rw-r--r--src/include/storage/proc.h15
-rw-r--r--src/include/storage/procarray.h21
-rw-r--r--src/include/storage/sinval.h5
-rw-r--r--src/include/storage/sinvaladt.h4
-rw-r--r--src/include/storage/standby.h106
-rw-r--r--src/include/utils/builtins.h3
-rw-r--r--src/include/utils/snapshot.h6
23 files changed, 362 insertions, 37 deletions
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index f31a505ddae..0f3eabce19c 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.144 2009/08/24 02:18:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.145 2009/12/19 01:32:42 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -130,11 +130,13 @@ extern XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf,
ItemPointerData from,
Buffer newbuf, HeapTuple newtup,
bool all_visible_cleared, bool new_all_visible_cleared);
+extern XLogRecPtr log_heap_cleanup_info(RelFileNode rnode,
+ TransactionId latestRemovedXid);
extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
OffsetNumber *redirected, int nredirected,
OffsetNumber *nowdead, int ndead,
OffsetNumber *nowunused, int nunused,
- bool redirect_move);
+ TransactionId latestRemovedXid, bool redirect_move);
extern XLogRecPtr log_heap_freeze(Relation reln, Buffer buffer,
TransactionId cutoff_xid,
OffsetNumber *offsets, int offcnt);
diff --git a/src/include/access/htup.h b/src/include/access/htup.h
index f7fa60cb70a..017f6917e16 100644
--- a/src/include/access/htup.h
+++ b/src/include/access/htup.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.107 2009/06/11 14:49:08 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.108 2009/12/19 01:32:42 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -580,6 +580,7 @@ typedef HeapTupleData *HeapTuple;
#define XLOG_HEAP2_FREEZE 0x00
#define XLOG_HEAP2_CLEAN 0x10
#define XLOG_HEAP2_CLEAN_MOVE 0x20
+#define XLOG_HEAP2_CLEANUP_INFO 0x30
/*
* All what we need to find changed tuple
@@ -668,6 +669,7 @@ typedef struct xl_heap_clean
{
RelFileNode node;
BlockNumber block;
+ TransactionId latestRemovedXid;
uint16 nredirected;
uint16 ndead;
/* OFFSET NUMBERS FOLLOW */
@@ -675,6 +677,19 @@ typedef struct xl_heap_clean
#define SizeOfHeapClean (offsetof(xl_heap_clean, ndead) + sizeof(uint16))
+/*
+ * Cleanup_info is required in some cases during a lazy VACUUM.
+ * Used for reporting the results of HeapTupleHeaderAdvanceLatestRemovedXid()
+ * see vacuumlazy.c for full explanation
+ */
+typedef struct xl_heap_cleanup_info
+{
+ RelFileNode node;
+ TransactionId latestRemovedXid;
+} xl_heap_cleanup_info;
+
+#define SizeOfHeapCleanupInfo (sizeof(xl_heap_cleanup_info))
+
/* This is for replacing a page's contents in toto */
/* NB: this is used for indexes as well as heaps */
typedef struct xl_heap_newpage
@@ -718,6 +733,9 @@ typedef struct xl_heap_freeze
#define SizeOfHeapFreeze (offsetof(xl_heap_freeze, cutoff_xid) + sizeof(TransactionId))
+extern void HeapTupleHeaderAdvanceLatestRemovedXid(HeapTupleHeader tuple,
+ TransactionId *latestRemovedXid);
+
/* HeapTupleHeader functions implemented in utils/time/combocid.c */
extern CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup);
extern CommandId HeapTupleHeaderGetCmax(HeapTupleHeader tup);
diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h
index ed5ec57e47f..bef4db461cf 100644
--- a/src/include/access/nbtree.h
+++ b/src/include/access/nbtree.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.125 2009/07/29 20:56:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.126 2009/12/19 01:32:42 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -214,12 +214,13 @@ typedef struct BTMetaPageData
#define XLOG_BTREE_SPLIT_R 0x40 /* as above, new item on right */
#define XLOG_BTREE_SPLIT_L_ROOT 0x50 /* add tuple with split of root */
#define XLOG_BTREE_SPLIT_R_ROOT 0x60 /* as above, new item on right */
-#define XLOG_BTREE_DELETE 0x70 /* delete leaf index tuple */
+#define XLOG_BTREE_DELETE 0x70 /* delete leaf index tuples for a page */
#define XLOG_BTREE_DELETE_PAGE 0x80 /* delete an entire page */
#define XLOG_BTREE_DELETE_PAGE_META 0x90 /* same, and update metapage */
#define XLOG_BTREE_NEWROOT 0xA0 /* new root page */
#define XLOG_BTREE_DELETE_PAGE_HALF 0xB0 /* page deletion that makes
* parent half-dead */
+#define XLOG_BTREE_VACUUM 0xC0 /* delete entries on a page during vacuum */
/*
* All that we need to find changed index tuple
@@ -306,16 +307,53 @@ typedef struct xl_btree_split
/*
* This is what we need to know about delete of individual leaf index tuples.
* The WAL record can represent deletion of any number of index tuples on a
- * single index page.
+ * single index page when *not* executed by VACUUM.
*/
typedef struct xl_btree_delete
{
RelFileNode node;
BlockNumber block;
+ TransactionId latestRemovedXid;
+ int numItems; /* number of items in the offset array */
+
/* TARGET OFFSET NUMBERS FOLLOW AT THE END */
} xl_btree_delete;
-#define SizeOfBtreeDelete (offsetof(xl_btree_delete, block) + sizeof(BlockNumber))
+#define SizeOfBtreeDelete (offsetof(xl_btree_delete, latestRemovedXid) + sizeof(TransactionId))
+
+/*
+ * This is what we need to know about vacuum of individual leaf index tuples.
+ * The WAL record can represent deletion of any number of index tuples on a
+ * single index page when executed by VACUUM.
+ *
+ * The correctness requirement for applying these changes during recovery is
+ * that we must do one of these two things for every block in the index:
+ * * lock the block for cleanup and apply any required changes
+ * * EnsureBlockUnpinned()
+ * The purpose of this is to ensure that no index scans started before we
+ * finish scanning the index are still running by the time we begin to remove
+ * heap tuples.
+ *
+ * Any changes to any one block are registered on just one WAL record. All
+ * blocks that we need to run EnsureBlockUnpinned() before we touch the changed
+ * block are also given on this record as a variable length array. The array
+ * is compressed by way of storing an array of block ranges, rather than an
+ * actual array of blockids.
+ *
+ * Note that the *last* WAL record in any vacuum of an index is allowed to
+ * have numItems == 0. All other WAL records must have numItems > 0.
+ */
+typedef struct xl_btree_vacuum
+{
+ RelFileNode node;
+ BlockNumber block;
+ BlockNumber lastBlockVacuumed;
+ int numItems; /* number of items in the offset array */
+
+ /* TARGET OFFSET NUMBERS FOLLOW */
+} xl_btree_vacuum;
+
+#define SizeOfBtreeVacuum (offsetof(xl_btree_vacuum, lastBlockVacuumed) + sizeof(BlockNumber))
/*
* This is what we need to know about deletion of a btree page. The target
@@ -537,7 +575,8 @@ extern void _bt_relbuf(Relation rel, Buffer buf);
extern void _bt_pageinit(Page page, Size size);
extern bool _bt_page_recyclable(Page page);
extern void _bt_delitems(Relation rel, Buffer buf,
- OffsetNumber *itemnos, int nitems);
+ OffsetNumber *itemnos, int nitems, bool isVacuum,
+ BlockNumber lastBlockVacuumed);
extern int _bt_pagedel(Relation rel, Buffer buf,
BTStack stack, bool vacuum_full);
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index eeca306d8bc..2761d1d8adc 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.67 2009/01/01 17:23:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.68 2009/12/19 01:32:42 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -68,6 +68,7 @@ typedef struct IndexScanDescData
/* signaling to index AM about killing index tuples */
bool kill_prior_tuple; /* last-returned tuple is dead */
bool ignore_killed_tuples; /* do not return killed entries */
+ bool xactStartedInRecovery; /* prevents killing/seeing killed tuples */
/* index access method's private state */
void *opaque; /* access-method-specific info */
diff --git a/src/include/access/rmgr.h b/src/include/access/rmgr.h
index 44b8a07a3fc..32b1bd535cc 100644
--- a/src/include/access/rmgr.h
+++ b/src/include/access/rmgr.h
@@ -3,7 +3,7 @@
*
* Resource managers definition
*
- * $PostgreSQL: pgsql/src/include/access/rmgr.h,v 1.19 2008/11/19 10:34:52 heikki Exp $
+ * $PostgreSQL: pgsql/src/include/access/rmgr.h,v 1.20 2009/12/19 01:32:42 sriggs Exp $
*/
#ifndef RMGR_H
#define RMGR_H
@@ -23,6 +23,7 @@ typedef uint8 RmgrId;
#define RM_DBASE_ID 4
#define RM_TBLSPC_ID 5
#define RM_MULTIXACT_ID 6
+#define RM_STANDBY_ID 8
#define RM_HEAP2_ID 9
#define RM_HEAP_ID 10
#define RM_BTREE_ID 11
diff --git a/src/include/access/subtrans.h b/src/include/access/subtrans.h
index 07941ac6c19..0658da0c5c7 100644
--- a/src/include/access/subtrans.h
+++ b/src/include/access/subtrans.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/subtrans.h,v 1.12 2009/01/01 17:23:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/subtrans.h,v 1.13 2009/12/19 01:32:42 sriggs Exp $
*/
#ifndef SUBTRANS_H
#define SUBTRANS_H
@@ -14,7 +14,7 @@
/* Number of SLRU buffers to use for subtrans */
#define NUM_SUBTRANS_BUFFERS 32
-extern void SubTransSetParent(TransactionId xid, TransactionId parent);
+extern void SubTransSetParent(TransactionId xid, TransactionId parent, bool overwriteOK);
extern TransactionId SubTransGetParent(TransactionId xid);
extern TransactionId SubTransGetTopmostTransaction(TransactionId xid);
diff --git a/src/include/access/transam.h b/src/include/access/transam.h
index 6f3370dcd2c..5917129f17a 100644
--- a/src/include/access/transam.h
+++ b/src/include/access/transam.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/transam.h,v 1.70 2009/09/01 04:46:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/transam.h,v 1.71 2009/12/19 01:32:42 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -129,6 +129,9 @@ typedef VariableCacheData *VariableCache;
* ----------------
*/
+/* in transam/xact.c */
+extern bool TransactionStartedDuringRecovery(void);
+
/* in transam/varsup.c */
extern PGDLLIMPORT VariableCache ShmemVariableCache;
diff --git a/src/include/access/twophase.h b/src/include/access/twophase.h
index 5652145f8ca..864d6d6da09 100644
--- a/src/include/access/twophase.h
+++ b/src/include/access/twophase.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/twophase.h,v 1.12 2009/11/23 09:58:36 heikki Exp $
+ * $PostgreSQL: pgsql/src/include/access/twophase.h,v 1.13 2009/12/19 01:32:42 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -40,8 +40,10 @@ extern GlobalTransaction MarkAsPreparing(TransactionId xid, const char *gid,
extern void StartPrepare(GlobalTransaction gxact);
extern void EndPrepare(GlobalTransaction gxact);
+extern bool StandbyTransactionIdIsPrepared(TransactionId xid);
-extern TransactionId PrescanPreparedTransactions(void);
+extern TransactionId PrescanPreparedTransactions(TransactionId **xids_p,
+ int *nxids_p);
extern void RecoverPreparedTransactions(void);
extern void RecreateTwoPhaseFile(TransactionId xid, void *content, int len);
diff --git a/src/include/access/twophase_rmgr.h b/src/include/access/twophase_rmgr.h
index 37d03495bc9..5fd5e10a785 100644
--- a/src/include/access/twophase_rmgr.h
+++ b/src/include/access/twophase_rmgr.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/twophase_rmgr.h,v 1.9 2009/11/23 09:58:36 heikki Exp $
+ * $PostgreSQL: pgsql/src/include/access/twophase_rmgr.h,v 1.10 2009/12/19 01:32:42 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,15 +23,15 @@ typedef uint8 TwoPhaseRmgrId;
*/
#define TWOPHASE_RM_END_ID 0
#define TWOPHASE_RM_LOCK_ID 1
-#define TWOPHASE_RM_INVAL_ID 2
-#define TWOPHASE_RM_NOTIFY_ID 3
-#define TWOPHASE_RM_PGSTAT_ID 4
-#define TWOPHASE_RM_MULTIXACT_ID 5
+#define TWOPHASE_RM_NOTIFY_ID 2
+#define TWOPHASE_RM_PGSTAT_ID 3
+#define TWOPHASE_RM_MULTIXACT_ID 4
#define TWOPHASE_RM_MAX_ID TWOPHASE_RM_MULTIXACT_ID
extern const TwoPhaseCallback twophase_recover_callbacks[];
extern const TwoPhaseCallback twophase_postcommit_callbacks[];
extern const TwoPhaseCallback twophase_postabort_callbacks[];
+extern const TwoPhaseCallback twophase_standby_recover_callbacks[];
extern void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info,
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index 880b41b7070..678a23da96c 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.98 2009/06/11 14:49:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.99 2009/12/19 01:32:42 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -84,19 +84,49 @@ typedef void (*SubXactCallback) (SubXactEvent event, SubTransactionId mySubid,
#define XLOG_XACT_ABORT 0x20
#define XLOG_XACT_COMMIT_PREPARED 0x30
#define XLOG_XACT_ABORT_PREPARED 0x40
+#define XLOG_XACT_ASSIGNMENT 0x50
+
+typedef struct xl_xact_assignment
+{
+ TransactionId xtop; /* assigned XID's top-level XID */
+ int nsubxacts; /* number of subtransaction XIDs */
+ TransactionId xsub[1]; /* assigned subxids */
+} xl_xact_assignment;
+
+#define MinSizeOfXactAssignment offsetof(xl_xact_assignment, xsub)
typedef struct xl_xact_commit
{
TimestampTz xact_time; /* time of commit */
+ uint32 xinfo; /* info flags */
int nrels; /* number of RelFileNodes */
int nsubxacts; /* number of subtransaction XIDs */
+ int nmsgs; /* number of shared inval msgs */
/* Array of RelFileNode(s) to drop at commit */
RelFileNode xnodes[1]; /* VARIABLE LENGTH ARRAY */
/* ARRAY OF COMMITTED SUBTRANSACTION XIDs FOLLOWS */
+ /* ARRAY OF SHARED INVALIDATION MESSAGES FOLLOWS */
} xl_xact_commit;
#define MinSizeOfXactCommit offsetof(xl_xact_commit, xnodes)
+/*
+ * These flags are set in the xinfo fields of WAL commit records,
+ * indicating a variety of additional actions that need to occur
+ * when emulating transaction effects during recovery.
+ * They are named XactCompletion... to differentiate them from
+ * EOXact... routines which run at the end of the original
+ * transaction completion.
+ */
+#define XACT_COMPLETION_UPDATE_RELCACHE_FILE 0x01
+#define XACT_COMPLETION_VACUUM_FULL 0x02
+#define XACT_COMPLETION_FORCE_SYNC_COMMIT 0x04
+
+/* Access macros for above flags */
+#define XactCompletionRelcacheInitFileInval(xlrec) ((xlrec)->xinfo & XACT_COMPLETION_UPDATE_RELCACHE_FILE)
+#define XactCompletionVacuumFull(xlrec) ((xlrec)->xinfo & XACT_COMPLETION_VACUUM_FULL)
+#define XactCompletionForceSyncCommit(xlrec) ((xlrec)->xinfo & XACT_COMPLETION_FORCE_SYNC_COMMIT)
+
typedef struct xl_xact_abort
{
TimestampTz xact_time; /* time of abort */
@@ -106,6 +136,7 @@ typedef struct xl_xact_abort
RelFileNode xnodes[1]; /* VARIABLE LENGTH ARRAY */
/* ARRAY OF ABORTED SUBTRANSACTION XIDs FOLLOWS */
} xl_xact_abort;
+/* Note the intentional lack of an invalidation message array c.f. commit */
#define MinSizeOfXactAbort offsetof(xl_xact_abort, xnodes)
@@ -181,7 +212,7 @@ extern void UnregisterXactCallback(XactCallback callback, void *arg);
extern void RegisterSubXactCallback(SubXactCallback callback, void *arg);
extern void UnregisterSubXactCallback(SubXactCallback callback, void *arg);
-extern TransactionId RecordTransactionCommit(void);
+extern TransactionId RecordTransactionCommit(bool isVacuumFull);
extern int xactGetCommittedChildren(TransactionId **ptr);
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 052a314d74e..ae624a08154 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.93 2009/06/26 20:29:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/xlog.h,v 1.94 2009/12/19 01:32:42 sriggs Exp $
*/
#ifndef XLOG_H
#define XLOG_H
@@ -133,7 +133,45 @@ typedef struct XLogRecData
} XLogRecData;
extern TimeLineID ThisTimeLineID; /* current TLI */
+
+/*
+ * Prior to 8.4, all activity during recovery was carried out by Startup
+ * process. This local variable continues to be used in many parts of the
+ * code to indicate actions taken by RecoveryManagers. Other processes who
+ * potentially perform work during recovery should check RecoveryInProgress()
+ * see XLogCtl notes in xlog.c
+ */
extern bool InRecovery;
+
+/*
+ * Like InRecovery, standbyState is only valid in the startup process.
+ *
+ * In DISABLED state, we're performing crash recovery or hot standby was
+ * disabled in recovery.conf.
+ *
+ * In INITIALIZED state, we haven't yet received a RUNNING_XACTS or shutdown
+ * checkpoint record to initialize our master transaction tracking system.
+ *
+ * When the transaction tracking is initialized, we enter the SNAPSHOT_PENDING
+ * state. The tracked information might still be incomplete, so we can't allow
+ * connections yet, but redo functions must update the in-memory state when
+ * appropriate.
+ *
+ * In SNAPSHOT_READY mode, we have full knowledge of transactions that are
+ * (or were) running in the master at the current WAL location. Snapshots
+ * can be taken, and read-only queries can be run.
+ */
+typedef enum
+{
+ STANDBY_DISABLED,
+ STANDBY_INITIALIZED,
+ STANDBY_SNAPSHOT_PENDING,
+ STANDBY_SNAPSHOT_READY
+} HotStandbyState;
+extern HotStandbyState standbyState;
+
+#define InHotStandby (standbyState >= STANDBY_SNAPSHOT_PENDING)
+
extern XLogRecPtr XactLastRecEnd;
/* these variables are GUC parameters related to XLOG */
@@ -143,9 +181,12 @@ extern bool XLogArchiveMode;
extern char *XLogArchiveCommand;
extern int XLogArchiveTimeout;
extern bool log_checkpoints;
+extern bool XLogRequestRecoveryConnections;
+extern int MaxStandbyDelay;
#define XLogArchivingActive() (XLogArchiveMode)
#define XLogArchiveCommandSet() (XLogArchiveCommand[0] != '\0')
+#define XLogStandbyInfoActive() (XLogRequestRecoveryConnections && XLogArchiveMode)
#ifdef WAL_DEBUG
extern bool XLOG_DEBUG;
@@ -203,6 +244,7 @@ extern void xlog_desc(StringInfo buf, uint8 xl_info, char *rec);
extern bool RecoveryInProgress(void);
extern bool XLogInsertAllowed(void);
+extern TimestampTz GetLatestXLogTime(void);
extern void UpdateControlFile(void);
extern Size XLOGShmemSize(void);
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 508c2eeb8de..9747dd8c963 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.25 2009/01/01 17:23:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/xlog_internal.h,v 1.26 2009/12/19 01:32:42 sriggs Exp $
*/
#ifndef XLOG_INTERNAL_H
#define XLOG_INTERNAL_H
@@ -71,7 +71,7 @@ typedef struct XLogContRecord
/*
* Each page of XLOG file has a header like this:
*/
-#define XLOG_PAGE_MAGIC 0xD063 /* can be used as WAL version indicator */
+#define XLOG_PAGE_MAGIC 0xD166 /* can be used as WAL version indicator */
typedef struct XLogPageHeaderData
{
@@ -255,5 +255,6 @@ extern Datum pg_current_xlog_location(PG_FUNCTION_ARGS);
extern Datum pg_current_xlog_insert_location(PG_FUNCTION_ARGS);
extern Datum pg_xlogfile_name_offset(PG_FUNCTION_ARGS);
extern Datum pg_xlogfile_name(PG_FUNCTION_ARGS);
+extern Datum pg_is_in_recovery(PG_FUNCTION_ARGS);
#endif /* XLOG_INTERNAL_H */
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index c7a740ca710..a4d19f8b4a1 100644
--- a/src/include/catalog/pg_control.h
+++ b/src/include/catalog/pg_control.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.44 2009/08/31 02:23:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_control.h,v 1.45 2009/12/19 01:32:42 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -40,6 +40,20 @@ typedef struct CheckPoint
TransactionId oldestXid; /* cluster-wide minimum datfrozenxid */
Oid oldestXidDB; /* database with minimum datfrozenxid */
pg_time_t time; /* time stamp of checkpoint */
+
+ /* Important parameter settings at time of shutdown checkpoints */
+ int MaxConnections;
+ int max_prepared_xacts;
+ int max_locks_per_xact;
+ bool XLogStandbyInfoMode;
+
+ /*
+ * Oldest XID still running. This is only needed to initialize hot standby
+ * mode from an online checkpoint, so we only bother calculating this for
+ * online checkpoints and only when archiving is enabled. Otherwise it's
+ * set to InvalidTransactionId.
+ */
+ TransactionId oldestActiveXid;
} CheckPoint;
/* XLOG info values for XLOG rmgr */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index c9307df58ab..ba5b49a5636 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.556 2009/12/06 02:55:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.557 2009/12/19 01:32:42 sriggs Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@@ -3285,6 +3285,9 @@ DESCR("xlog filename and byte offset, given an xlog location");
DATA(insert OID = 2851 ( pg_xlogfile_name PGNSP PGUID 12 1 0 0 f f f t f i 1 0 25 "25" _null_ _null_ _null_ _null_ pg_xlogfile_name _null_ _null_ _null_ ));
DESCR("xlog filename, given an xlog location");
+DATA(insert OID = 3810 ( pg_is_in_recovery PGNSP PGUID 12 1 0 0 f f f t f v 0 0 16 "" _null_ _null_ _null_ _null_ pg_is_in_recovery _null_ _null_ _null_ ));
+DESCR("true if server is in recovery");
+
DATA(insert OID = 2621 ( pg_reload_conf PGNSP PGUID 12 1 0 0 f f f t f v 0 0 16 "" _null_ _null_ _null_ _null_ pg_reload_conf _null_ _null_ _null_ ));
DESCR("reload configuration files");
DATA(insert OID = 2622 ( pg_rotate_logfile PGNSP PGUID 12 1 0 0 f f f t f v 0 0 16 "" _null_ _null_ _null_ _null_ pg_rotate_logfile _null_ _null_ _null_ ));
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 424af2e56ae..da46c494967 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.215 2009/12/09 21:57:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.216 2009/12/19 01:32:41 sriggs Exp $
*
* NOTES
* some of the information in this file should be moved to other files.
@@ -236,6 +236,12 @@ extern bool VacuumCostActive;
/* in tcop/postgres.c */
extern void check_stack_depth(void);
+/* in tcop/utility.c */
+extern void PreventCommandDuringRecovery(void);
+
+/* in utils/misc/guc.c */
+extern int trace_recovery_messages;
+int trace_recovery(int trace_level);
/*****************************************************************************
* pdir.h -- *
diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h
index e2b27ccb98b..2749b833f64 100644
--- a/src/include/storage/lock.h
+++ b/src/include/storage/lock.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.116 2009/04/04 17:40:36 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.117 2009/12/19 01:32:44 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -477,6 +477,11 @@ extern LockAcquireResult LockAcquire(const LOCKTAG *locktag,
LOCKMODE lockmode,
bool sessionLock,
bool dontWait);
+extern LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag,
+ LOCKMODE lockmode,
+ bool sessionLock,
+ bool dontWait,
+ bool report_memory_error);
extern bool LockRelease(const LOCKTAG *locktag,
LOCKMODE lockmode, bool sessionLock);
extern void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks);
@@ -494,6 +499,17 @@ extern void GrantAwaitedLock(void);
extern void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode);
extern Size LockShmemSize(void);
extern LockData *GetLockStatusData(void);
+
+extern void ReportLockTableError(bool report);
+
+typedef struct xl_standby_lock
+{
+ TransactionId xid; /* xid of holder of AccessExclusiveLock */
+ Oid dbOid;
+ Oid relOid;
+} xl_standby_lock;
+
+extern xl_standby_lock *GetRunningTransactionLocks(int *nlocks);
extern const char *GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode);
extern void lock_twophase_recover(TransactionId xid, uint16 info,
@@ -502,6 +518,8 @@ extern void lock_twophase_postcommit(TransactionId xid, uint16 info,
void *recdata, uint32 len);
extern void lock_twophase_postabort(TransactionId xid, uint16 info,
void *recdata, uint32 len);
+extern void lock_twophase_standby_recover(TransactionId xid, uint16 info,
+ void *recdata, uint32 len);
extern DeadLockState DeadLockCheck(PGPROC *proc);
extern PGPROC *GetBlockingAutoVacuumPgproc(void);
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index c8a9042fdc8..cc555291287 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.114 2009/08/31 19:41:00 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.115 2009/12/19 01:32:44 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -95,6 +95,13 @@ struct PGPROC
uint8 vacuumFlags; /* vacuum-related flags, see above */
+ /*
+ * While in hot standby mode, setting recoveryConflictMode instructs
+ * the backend to commit suicide. Possible values are the same as those
+ * passed to ResolveRecoveryConflictWithVirtualXIDs().
+ */
+ int recoveryConflictMode;
+
/* Info about LWLock the process is currently waiting for, if any. */
bool lwWaiting; /* true if waiting for an LW lock */
bool lwExclusive; /* true if waiting for exclusive access */
@@ -135,6 +142,9 @@ typedef struct PROC_HDR
PGPROC *autovacFreeProcs;
/* Current shared estimate of appropriate spins_per_delay value */
int spins_per_delay;
+ /* The proc of the Startup process, since not in ProcArray */
+ PGPROC *startupProc;
+ int startupProcPid;
} PROC_HDR;
/*
@@ -165,6 +175,9 @@ extern void InitProcGlobal(void);
extern void InitProcess(void);
extern void InitProcessPhase2(void);
extern void InitAuxiliaryProcess(void);
+
+extern void PublishStartupProcessInformation(void);
+
extern bool HaveNFreeProcs(int n);
extern void ProcReleaseLocks(bool isCommit);
diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index fab84ee1a09..a7fb379cf65 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/procarray.h,v 1.26 2009/06/11 14:49:12 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/procarray.h,v 1.27 2009/12/19 01:32:44 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -15,6 +15,7 @@
#define PROCARRAY_H
#include "storage/lock.h"
+#include "storage/standby.h"
#include "utils/snapshot.h"
@@ -26,6 +27,19 @@ extern void ProcArrayRemove(PGPROC *proc, TransactionId latestXid);
extern void ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid);
extern void ProcArrayClearTransaction(PGPROC *proc);
+extern void ProcArrayInitRecoveryInfo(TransactionId oldestActiveXid);
+extern void ProcArrayApplyRecoveryInfo(RunningTransactions running);
+extern void ProcArrayApplyXidAssignment(TransactionId topxid,
+ int nsubxids, TransactionId *subxids);
+
+extern void RecordKnownAssignedTransactionIds(TransactionId xid);
+extern void ExpireTreeKnownAssignedTransactionIds(TransactionId xid,
+ int nsubxids, TransactionId *subxids);
+extern void ExpireAllKnownAssignedTransactionIds(void);
+extern void ExpireOldKnownAssignedTransactionIds(TransactionId xid);
+
+extern RunningTransactions GetRunningTransactionData(void);
+
extern Snapshot GetSnapshotData(Snapshot snapshot);
extern bool TransactionIdIsInProgress(TransactionId xid);
@@ -42,6 +56,11 @@ extern bool IsBackendPid(int pid);
extern VirtualTransactionId *GetCurrentVirtualXIDs(TransactionId limitXmin,
bool excludeXmin0, bool allDbs, int excludeVacuum,
int *nvxids);
+extern VirtualTransactionId *GetConflictingVirtualXIDs(TransactionId limitXmin,
+ Oid dbOid, bool skipExistingConflicts);
+extern pid_t CancelVirtualTransaction(VirtualTransactionId vxid,
+ int cancel_mode);
+
extern int CountActiveBackends(void);
extern int CountDBBackends(Oid databaseid);
extern int CountUserBackends(Oid roleid);
diff --git a/src/include/storage/sinval.h b/src/include/storage/sinval.h
index 84edb5b31e3..2dbebaf9f7a 100644
--- a/src/include/storage/sinval.h
+++ b/src/include/storage/sinval.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/sinval.h,v 1.53 2009/07/31 20:26:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/sinval.h,v 1.54 2009/12/19 01:32:44 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -100,4 +100,7 @@ extern void HandleCatchupInterrupt(void);
extern void EnableCatchupInterrupt(void);
extern bool DisableCatchupInterrupt(void);
+extern int xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs,
+ bool *RelcacheInitFileInval);
+
#endif /* SINVAL_H */
diff --git a/src/include/storage/sinvaladt.h b/src/include/storage/sinvaladt.h
index 87a8c6d3a18..5d188aaa2f6 100644
--- a/src/include/storage/sinvaladt.h
+++ b/src/include/storage/sinvaladt.h
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/sinvaladt.h,v 1.51 2009/06/11 14:49:12 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/sinvaladt.h,v 1.52 2009/12/19 01:32:44 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -29,7 +29,7 @@
*/
extern Size SInvalShmemSize(void);
extern void CreateSharedInvalidationState(void);
-extern void SharedInvalBackendInit(void);
+extern void SharedInvalBackendInit(bool sendOnly);
extern bool BackendIdIsActive(int backendID);
extern void SIInsertDataEntries(const SharedInvalidationMessage *data, int n);
diff --git a/src/include/storage/standby.h b/src/include/storage/standby.h
new file mode 100644
index 00000000000..45d44f60f6b
--- /dev/null
+++ b/src/include/storage/standby.h
@@ -0,0 +1,106 @@
+/*-------------------------------------------------------------------------
+ *
+ * standby.h
+ * Definitions for hot standby mode.
+ *
+ *
+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $PostgreSQL: pgsql/src/include/storage/standby.h,v 1.1 2009/12/19 01:32:44 sriggs Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef STANDBY_H
+#define STANDBY_H
+
+#include "access/xlog.h"
+#include "storage/lock.h"
+
+extern int vacuum_defer_cleanup_age;
+
+/* cancel modes for ResolveRecoveryConflictWithVirtualXIDs */
+#define CONFLICT_MODE_NOT_SET 0
+#define CONFLICT_MODE_ERROR 1 /* Conflict can be resolved by canceling query */
+#define CONFLICT_MODE_FATAL 2 /* Conflict can only be resolved by disconnecting session */
+
+extern void ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist,
+ char *reason, int cancel_mode);
+
+extern void InitRecoveryTransactionEnvironment(void);
+extern void ShutdownRecoveryTransactionEnvironment(void);
+
+/*
+ * Standby Rmgr (RM_STANDBY_ID)
+ *
+ * Standby recovery manager exists to perform actions that are required
+ * to make hot standby work. That includes logging AccessExclusiveLocks taken
+ * by transactions and running-xacts snapshots.
+ */
+extern void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid);
+extern void StandbyReleaseLockTree(TransactionId xid,
+ int nsubxids, TransactionId *subxids);
+extern void StandbyReleaseAllLocks(void);
+extern void StandbyReleaseOldLocks(TransactionId removeXid);
+
+/*
+ * XLOG message types
+ */
+#define XLOG_STANDBY_LOCK 0x00
+#define XLOG_RUNNING_XACTS 0x10
+
+typedef struct xl_standby_locks
+{
+ int nlocks; /* number of entries in locks array */
+ xl_standby_lock locks[1]; /* VARIABLE LENGTH ARRAY */
+} xl_standby_locks;
+
+/*
+ * When we write running xact data to WAL, we use this structure.
+ */
+typedef struct xl_running_xacts
+{
+ int xcnt; /* # of xact ids in xids[] */
+ bool subxid_overflow; /* snapshot overflowed, subxids missing */
+ TransactionId nextXid; /* copy of ShmemVariableCache->nextXid */
+ TransactionId oldestRunningXid; /* *not* oldestXmin */
+
+ TransactionId xids[1]; /* VARIABLE LENGTH ARRAY */
+} xl_running_xacts;
+
+#define MinSizeOfXactRunningXacts offsetof(xl_running_xacts, xids)
+
+
+/* Recovery handlers for the Standby Rmgr (RM_STANDBY_ID) */
+extern void standby_redo(XLogRecPtr lsn, XLogRecord *record);
+extern void standby_desc(StringInfo buf, uint8 xl_info, char *rec);
+
+/*
+ * Declarations for GetRunningTransactionData(). Similar to Snapshots, but
+ * not quite. This has nothing at all to do with visibility on this server,
+ * so this is completely separate from snapmgr.c and snapmgr.h
+ * This data is important for creating the initial snapshot state on a
+ * standby server. We need lots more information than a normal snapshot,
+ * hence we use a specific data structure for our needs. This data
+ * is written to WAL as a separate record immediately after each
+ * checkpoint. That means that wherever we start a standby from we will
+ * almost immediately see the data we need to begin executing queries.
+ */
+
+typedef struct RunningTransactionsData
+{
+ int xcnt; /* # of xact ids in xids[] */
+ bool subxid_overflow; /* snapshot overflowed, subxids missing */
+ TransactionId nextXid; /* copy of ShmemVariableCache->nextXid */
+ TransactionId oldestRunningXid; /* *not* oldestXmin */
+
+ TransactionId *xids; /* array of (sub)xids still running */
+} RunningTransactionsData;
+
+typedef RunningTransactionsData *RunningTransactions;
+
+extern void LogAccessExclusiveLock(Oid dbOid, Oid relOid);
+
+extern void LogStandbySnapshot(TransactionId *oldestActiveXid, TransactionId *nextXid);
+
+#endif /* STANDBY_H */
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index c400c67e0ec..67b98632e0d 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.341 2009/10/21 20:38:58 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.342 2009/12/19 01:32:44 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -730,6 +730,7 @@ extern Datum xidrecv(PG_FUNCTION_ARGS);
extern Datum xidsend(PG_FUNCTION_ARGS);
extern Datum xideq(PG_FUNCTION_ARGS);
extern Datum xid_age(PG_FUNCTION_ARGS);
+extern int xidComparator(const void *arg1, const void *arg2);
extern Datum cidin(PG_FUNCTION_ARGS);
extern Datum cidout(PG_FUNCTION_ARGS);
extern Datum cidrecv(PG_FUNCTION_ARGS);
diff --git a/src/include/utils/snapshot.h b/src/include/utils/snapshot.h
index e5003b669a1..18094180c4e 100644
--- a/src/include/utils/snapshot.h
+++ b/src/include/utils/snapshot.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/snapshot.h,v 1.5 2009/06/11 14:49:13 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/snapshot.h,v 1.6 2009/12/19 01:32:44 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -49,8 +49,10 @@ typedef struct SnapshotData
uint32 xcnt; /* # of xact ids in xip[] */
TransactionId *xip; /* array of xact IDs in progress */
/* note: all ids in xip[] satisfy xmin <= xip[i] < xmax */
- int32 subxcnt; /* # of xact ids in subxip[], -1 if overflow */
+ int32 subxcnt; /* # of xact ids in subxip[] */
TransactionId *subxip; /* array of subxact IDs in progress */
+ bool suboverflowed; /* has the subxip array overflowed? */
+ bool takenDuringRecovery; /* recovery-shaped snapshot? */
/*
* note: all ids in subxip[] are >= xmin, but we don't bother filtering