From dd428c79a4d89867758443b7b5aac45137685f11 Mon Sep 17 00:00:00 2001
From: Simon Riggs <simon@2ndQuadrant.com>
Date: Sat, 13 Feb 2010 16:15:48 +0000
Subject: [PATCH] Fix relcache init file invalidation during Hot Standby for
 the case where a database has a non-default tablespaceid. Pass thru
 MyDatabaseId and MyDatabaseTableSpace to allow file path to be re-created in
 standby and correct invalidation to take place in all cases. Update and
 rework xact_commit_desc() debug messages. Bug report from Tom by code
 inspection. Fix by me.

---
 src/backend/access/transam/xact.c | 22 ++++++---
 src/backend/utils/cache/inval.c   | 82 +++----------------------------
 src/include/access/xact.h         |  6 ++-
 src/include/storage/sinval.h      |  5 +-
 4 files changed, 30 insertions(+), 85 deletions(-)

diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 27ce9ac4c30..c239c098fd6 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.284 2010/02/08 04:33:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.285 2010/02/13 16:15:46 sriggs Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -951,6 +951,9 @@ RecordTransactionCommit(void)
 		if (forceSyncCommit)
 			xlrec.xinfo |= XACT_COMPLETION_FORCE_SYNC_COMMIT;
 
+		xlrec.dbId = MyDatabaseId;
+		xlrec.tsId = MyDatabaseTableSpace;
+
 		/*
 		 * Mark ourselves as within our "commit critical section".	This
 		 * forces any concurrent checkpoint to wait until we've updated
@@ -4412,7 +4415,8 @@ xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
 		 * as occurs in 	.
 		 */
 		ProcessCommittedInvalidationMessages(inval_msgs, xlrec->nmsgs,
-									XactCompletionRelcacheInitFileInval(xlrec));
+									XactCompletionRelcacheInitFileInval(xlrec),
+									xlrec->dbId, xlrec->tsId);
 
 		/*
 		 * Release locks, if any. We do this for both two phase and normal
@@ -4596,15 +4600,11 @@ xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
 {
 	int			i;
 	TransactionId *xacts;
-	SharedInvalidationMessage *msgs;
 
 	xacts = (TransactionId *) &xlrec->xnodes[xlrec->nrels];
-	msgs = (SharedInvalidationMessage *) &xacts[xlrec->nsubxacts];
-
-	if (XactCompletionRelcacheInitFileInval(xlrec))
-		appendStringInfo(buf, "; relcache init file inval");
 
 	appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
+
 	if (xlrec->nrels > 0)
 	{
 		appendStringInfo(buf, "; rels:");
@@ -4624,6 +4624,14 @@ xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
 	}
 	if (xlrec->nmsgs > 0)
 	{
+		SharedInvalidationMessage *msgs;
+
+		msgs = (SharedInvalidationMessage *) &xacts[xlrec->nsubxacts];
+
+		if (XactCompletionRelcacheInitFileInval(xlrec))
+			appendStringInfo(buf, "; relcache init file inval dbid %u tsid %u", 
+										xlrec->dbId, xlrec->tsId);
+
 		appendStringInfo(buf, "; inval msgs:");
 		for (i = 0; i < xlrec->nmsgs; i++)
 		{
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 86b88ba0571..54a7af80534 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -80,7 +80,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.95 2010/02/08 04:33:54 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.96 2010/02/13 16:15:47 sriggs Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -861,15 +861,6 @@ xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs,
  * ProcessCommittedInvalidationMessages is executed by xact_redo_commit()
  * to process invalidation messages added to commit records.
  *
- * If we have to invalidate the relcache init file we need to extract
- * the database id from each message so we can correctly locate the database
- * path and so remove that database's init file. We note that the relcache
- * only contains entries for catalog tables from a single database, or
- * shared relations. There are smgr invalidations that reference other
- * databases but they never cause relcache file invalidations.
- * So we only need to access either global or default tablespaces and
- * never have need to scan pg_database to discover tablespace oids.
- *
  * Relcache init file invalidation requires processing both
  * before and after we send the SI messages. See AtEOXact_Inval()
  *
@@ -879,79 +870,22 @@ xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs,
  */
 void
 ProcessCommittedInvalidationMessages(SharedInvalidationMessage *msgs,
-									 int nmsgs, bool RelcacheInitFileInval)
+									 int nmsgs, bool RelcacheInitFileInval,
+									 Oid dbid, Oid tsid)
 {
-	Oid 		dboid = 0;
-	bool		invalidate_global = false;
+	if (nmsgs <= 0)
+		return;
 
-	if (nmsgs > 0)
-		elog(trace_recovery(DEBUG4), "replaying commit with %d messages%s", nmsgs,
+	elog(trace_recovery(DEBUG4), "replaying commit with %d messages%s", nmsgs,
 					(RelcacheInitFileInval ? " and relcache file invalidation" : ""));
-	else
-		return;
 
 	if (RelcacheInitFileInval)
-	{
-		int			i;
-
-		/*
-		 * Check messages to record dboid
-		 */
-		for (i = 0; i < nmsgs; i++)
-		{
-			SharedInvalidationMessage *inval_msg = &(msgs[i]);
-			Oid 		loop_dboid = 0;
-
-			/*
-			 * Extract the database Oid from the message
-			 */
-			if (inval_msg->id >= 0)
-				loop_dboid = inval_msg->cc.dbId;
-			else if (inval_msg->id == SHAREDINVALRELCACHE_ID)
-				loop_dboid = inval_msg->rc.dbId;
-			else
-			{
-				/*
-				 * Invalidation message is a catalog or nontransactional inval,
-				 * which never cause relcache file invalidation,
-				 * so we ignore them, no matter which db they're for.
-				 */
-				continue;
-			}
-
-			if (loop_dboid == 0)
-				invalidate_global = true;
-			else
-			{
-				Assert(dboid == 0 || dboid == loop_dboid);
-				dboid = loop_dboid;
-			}
-		}
-
-		/*
-		 * If shared, dboid will be the global tablespace, otherwise it will
-		 * be a local catalog relation in the default tablespace.
-		 */
-		if (invalidate_global)
-			RecoveryRelationCacheInitFileInvalidate(0, GLOBALTABLESPACE_OID, true);
-
-		if (dboid != 0)
-			RecoveryRelationCacheInitFileInvalidate(dboid, DEFAULTTABLESPACE_OID, true);
-	}
+		RecoveryRelationCacheInitFileInvalidate(dbid, tsid, true);
 
 	SendSharedInvalidMessages(msgs, nmsgs);
 
 	if (RelcacheInitFileInval)
-	{
-		/*
-		 * Second invalidation, very similar to above. See RelationCacheInitFileInvalidate()
-		 */
-		if (invalidate_global)
-			RecoveryRelationCacheInitFileInvalidate(0, GLOBALTABLESPACE_OID, false);
-
-		if (dboid != 0)
-			RecoveryRelationCacheInitFileInvalidate(dboid, DEFAULTTABLESPACE_OID, false);
-	}
+		RecoveryRelationCacheInitFileInvalidate(dbid, tsid, false);
 }
 
 /*
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index 27913aa8df2..fb9f22d5427 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.101 2010/02/08 04:33:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.102 2010/02/13 16:15:47 sriggs Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -102,6 +102,8 @@ typedef struct xl_xact_commit
 	int			nrels;			/* number of RelFileNodes */
 	int			nsubxacts;		/* number of subtransaction XIDs */
 	int			nmsgs;			/* number of shared inval msgs */
+	Oid			dbId;			/* MyDatabaseId */
+	Oid			tsId;			/* MyDatabaseTableSpace */
 	/* Array of RelFileNode(s) to drop at commit */
 	RelFileNode xnodes[1];		/* VARIABLE LENGTH ARRAY */
 	/* ARRAY OF COMMITTED SUBTRANSACTION XIDs FOLLOWS */
@@ -119,7 +121,7 @@ typedef struct xl_xact_commit
  * transaction completion.
  */
 #define XACT_COMPLETION_UPDATE_RELCACHE_FILE	0x01
-#define XACT_COMPLETION_FORCE_SYNC_COMMIT		0x04
+#define XACT_COMPLETION_FORCE_SYNC_COMMIT		0x02
 
 /* Access macros for above flags */
 #define XactCompletionRelcacheInitFileInval(xlrec)	((xlrec)->xinfo & XACT_COMPLETION_UPDATE_RELCACHE_FILE)
diff --git a/src/include/storage/sinval.h b/src/include/storage/sinval.h
index bad8f505427..70148c3f27a 100644
--- a/src/include/storage/sinval.h
+++ b/src/include/storage/sinval.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/sinval.h,v 1.57 2010/02/07 20:48:13 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/sinval.h,v 1.58 2010/02/13 16:15:48 sriggs Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -134,6 +134,7 @@ extern bool DisableCatchupInterrupt(void);
 extern int xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs,
 										bool *RelcacheInitFileInval);
 extern void ProcessCommittedInvalidationMessages(SharedInvalidationMessage *msgs,
-										int nmsgs, bool RelcacheInitFileInval);
+										int nmsgs, bool RelcacheInitFileInval,
+										Oid dbid, Oid tsid);
 
 #endif   /* SINVAL_H */
-- 
GitLab