diff options
Diffstat (limited to 'src/backend/utils/cache/inval.c')
-rw-r--r-- | src/backend/utils/cache/inval.c | 108 |
1 files changed, 107 insertions, 1 deletions
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c index 0dfef0016fe..04935ffd546 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.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 $ * *------------------------------------------------------------------------- */ @@ -89,6 +89,7 @@ #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,6 +872,111 @@ xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs, 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. |