*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.279 2010/01/02 16:57:35 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.280 2010/01/09 16:49:27 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
* 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);
- }
+ ProcessCommittedInvalidationMessages(inval_msgs, xlrec->nmsgs,
+ XactCompletionRelcacheInitFileInval(xlrec));
/*
* Release locks, if any. We do this for both two phase and normal
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.91 2010/01/02 16:57:55 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.92 2010/01/09 16:49:27 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
#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"
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 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()
+ *
+ * We deliberately avoid SetDatabasePath() since it is intended to be used
+ * only once by normal backends, so we set DatabasePath directly then
+ * pfree after use. See RecoveryRelationCacheInitFileInvalidate() macro.
+ */
+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, 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);
+ }
+
+ 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);
+ }
+}
+
/*
* AtEOXact_Inval
* Process queued-up invalidation messages at end of main transaction.