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 (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers