On Fri, 2010-01-08 at 01:26 +0000, Simon Riggs wrote:
> I'll test and commit tomorrow, since it's a fairly standalone problem
Fix attached, thanks for testing.
Works for me and I don't expect it to fail on Solaris, since the root
cause of the failure has been addressed and a correctly designed test
executed.
I will wait a day for your confirmation and/or other's comments.
--
Simon Riggs www.2ndQuadrant.com
*** a/src/backend/access/transam/xact.c
--- b/src/backend/access/transam/xact.c
***************
*** 4404,4423 **** xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
* maintain the same order of invalidation then release locks
* as occurs in .
*/
! if (xlrec->nmsgs > 0)
! {
! /*
! * Relcache init file invalidation requires processing both
! * before and after we send the SI messages. See AtEOXact_Inval()
! */
! if (XactCompletionRelcacheInitFileInval(xlrec))
! RelationCacheInitFileInvalidate(true);
!
! SendSharedInvalidMessages(inval_msgs, xlrec->nmsgs);
!
! if (XactCompletionRelcacheInitFileInval(xlrec))
! RelationCacheInitFileInvalidate(false);
! }
/*
* Release locks, if any. We do this for both two phase and normal
--- 4404,4411 ----
* maintain the same order of invalidation then release locks
* as occurs in .
*/
! ProcessCommittedInvalidationMessages(inval_msgs, xlrec->nmsgs,
! XactCompletionRelcacheInitFileInval(xlrec));
/*
* Release locks, if any. We do this for both two phase and normal
*** a/src/backend/utils/cache/inval.c
--- b/src/backend/utils/cache/inval.c
***************
*** 89,94 ****
--- 89,95 ----
#include "access/twophase_rmgr.h"
#include "access/xact.h"
#include "catalog/catalog.h"
+ #include "catalog/pg_tablespace.h"
#include "miscadmin.h"
#include "storage/sinval.h"
#include "storage/smgr.h"
***************
*** 871,876 **** xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs,
--- 872,981 ----
return numSharedInvalidMessagesArray;
}
+ #define RecoveryRelationCacheInitFileInvalidate(dbo, tbo, tf) \
+ { \
+ DatabasePath = GetDatabasePath(dbo, tbo); \
+ elog(trace_recovery(DEBUG4), "removing relcache init file in %s", DatabasePath); \
+ RelationCacheInitFileInvalidate(tf); \
+ pfree(DatabasePath); \
+ }
+
+ /*
+ * 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 need not scan pg_database to discover tablespace oids, since
+ * we only have either global or default tablespaces. Just lucky, I guess.
+ *
+ * Relcache init file invalidation requires processing both
+ * before and after we send the SI messages. See AtEOXact_Inval()
+ *
+ * We deliberately avoid SetDatabasePath() since it is intended to be used
+ * only once by normal backends, so we just use DatabasePath directly and
+ * immediately pfree after use.
+ */
+ void
+ ProcessCommittedInvalidationMessages(SharedInvalidationMessage *msgs,
+ int nmsgs, bool RelcacheInitFileInval)
+ {
+ Oid dboid = 0;
+ bool invalidate_global = false;
+
+ if (nmsgs > 0)
+ 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 SHAREDINVALSMGR_ID
+ * which never cause relcache file invalidation,
+ * so we ignore them, whichever database they're for.
+ */
+ }
+
+ 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 shared catalog relation in the default tablespace.
+ */
+ if (invalidate_global)
+ RecoveryRelationCacheInitFileInvalidate(0, GLOBALTABLESPACE_OID, true);
+
+ if (dboid != 0)
+ RecoveryRelationCacheInitFileInvalidate(dboid, DEFAULTTABLESPACE_OID, true);
+ }
+
+ SendSharedInvalidMessages(msgs, nmsgs);
+
+ if (RelcacheInitFileInval)
+ {
+ /*
+ * Second invalidation, very similar to above.
+ */
+ if (invalidate_global)
+ RecoveryRelationCacheInitFileInvalidate(0, GLOBALTABLESPACE_OID, false);
+
+ if (dboid != 0)
+ RecoveryRelationCacheInitFileInvalidate(dboid, DEFAULTTABLESPACE_OID, false);
+ }
+ }
+
/*
* AtEOXact_Inval
* Process queued-up invalidation messages at end of main transaction.
*** a/src/include/storage/sinval.h
--- b/src/include/storage/sinval.h
***************
*** 102,106 **** extern bool DisableCatchupInterrupt(void);
--- 102,108 ----
extern int xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs,
bool *RelcacheInitFileInval);
+ extern void ProcessCommittedInvalidationMessages(SharedInvalidationMessage *msgs,
+ int nmsgs, bool RelcacheInitFileInval);
#endif /* SINVAL_H */
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers