aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/inval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache/inval.c')
-rw-r--r--src/backend/utils/cache/inval.c130
1 files changed, 44 insertions, 86 deletions
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 04935ffd546..99aad752bb3 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -53,14 +53,14 @@
*
* Also, whenever we see an operation on a pg_class or pg_attribute tuple,
* we register a relcache flush operation for the relation described by that
- * tuple. pg_class updates trigger an smgr flush operation as well.
+ * tuple.
*
- * We keep the relcache and smgr flush requests in lists separate from the
- * catcache tuple flush requests. This allows us to issue all the pending
- * catcache flushes before we issue relcache flushes, which saves us from
- * loading a catcache tuple during relcache load only to flush it again
- * right away. Also, we avoid queuing multiple relcache flush requests for
- * the same relation, since a relcache flush is relatively expensive to do.
+ * We keep the relcache flush requests in lists separate from the catcache
+ * tuple flush requests. This allows us to issue all the pending catcache
+ * flushes before we issue relcache flushes, which saves us from loading
+ * a catcache tuple during relcache load only to flush it again right away.
+ * Also, we avoid queuing multiple relcache flush requests for the same
+ * relation, since a relcache flush is relatively expensive to do.
* (XXX is it worth testing likewise for duplicate catcache flush entries?
* Probably not.)
*
@@ -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.92 2010/01/09 16:49:27 sriggs Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.93 2010/02/03 01:14:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -116,7 +116,7 @@ typedef struct InvalidationChunk
typedef struct InvalidationListHeader
{
InvalidationChunk *cclist; /* list of chunks holding catcache msgs */
- InvalidationChunk *rclist; /* list of chunks holding relcache/smgr msgs */
+ InvalidationChunk *rclist; /* list of chunks holding relcache msgs */
} InvalidationListHeader;
/*----------------
@@ -304,7 +304,7 @@ AppendInvalidationMessageList(InvalidationChunk **destHdr,
* Invalidation set support functions
*
* These routines understand about the division of a logical invalidation
- * list into separate physical lists for catcache and relcache/smgr entries.
+ * list into separate physical lists for catcache and relcache entries.
* ----------------------------------------------------------------
*/
@@ -349,27 +349,6 @@ AddRelcacheInvalidationMessage(InvalidationListHeader *hdr,
}
/*
- * Add an smgr inval entry
- */
-static void
-AddSmgrInvalidationMessage(InvalidationListHeader *hdr,
- RelFileNode rnode)
-{
- SharedInvalidationMessage msg;
-
- /* Don't add a duplicate item */
- ProcessMessageList(hdr->rclist,
- if (msg->sm.id == SHAREDINVALSMGR_ID &&
- RelFileNodeEquals(msg->sm.rnode, rnode))
- return);
-
- /* OK, add the item */
- msg.sm.id = SHAREDINVALSMGR_ID;
- msg.sm.rnode = rnode;
- AddInvalidationMessage(&hdr->rclist, &msg);
-}
-
-/*
* Append one list of invalidation messages to another, resetting
* the source list to empty.
*/
@@ -455,23 +434,6 @@ RegisterRelcacheInvalidation(Oid dbId, Oid relId)
}
/*
- * RegisterSmgrInvalidation
- *
- * As above, but register an smgr invalidation event.
- */
-static void
-RegisterSmgrInvalidation(RelFileNode rnode)
-{
- AddSmgrInvalidationMessage(&transInvalInfo->CurrentCmdInvalidMsgs,
- rnode);
-
- /*
- * As above, just in case there is not an associated catalog change.
- */
- (void) GetCurrentCommandId(true);
-}
-
-/*
* LocalExecuteInvalidationMessage
*
* Process a single invalidation message (which could be of any type).
@@ -606,35 +568,12 @@ PrepareForTupleInvalidation(Relation relation, HeapTuple tuple)
if (tupleRelId == RelationRelationId)
{
Form_pg_class classtup = (Form_pg_class) GETSTRUCT(tuple);
- RelFileNode rnode;
relationId = HeapTupleGetOid(tuple);
if (classtup->relisshared)
databaseId = InvalidOid;
else
databaseId = MyDatabaseId;
-
- /*
- * We need to send out an smgr inval as well as a relcache inval. This
- * is needed because other backends might possibly possess smgr cache
- * but not relcache entries for the target relation.
- *
- * Note: during a pg_class row update that assigns a new relfilenode
- * or reltablespace value, we will be called on both the old and new
- * tuples, and thus will broadcast invalidation messages showing both
- * the old and new RelFileNode values. This ensures that other
- * backends will close smgr references to the old file.
- *
- * XXX possible future cleanup: it might be better to trigger smgr
- * flushes explicitly, rather than indirectly from pg_class updates.
- */
- if (classtup->reltablespace)
- rnode.spcNode = classtup->reltablespace;
- else
- rnode.spcNode = MyDatabaseTableSpace;
- rnode.dbNode = databaseId;
- rnode.relNode = classtup->relfilenode;
- RegisterSmgrInvalidation(rnode);
}
else if (tupleRelId == AttributeRelationId)
{
@@ -902,7 +841,7 @@ xactGetCommittedInvalidationMessages(SharedInvalidationMessage **msgs,
*/
void
ProcessCommittedInvalidationMessages(SharedInvalidationMessage *msgs,
- int nmsgs, bool RelcacheInitFileInval)
+ int nmsgs, bool RelcacheInitFileInval)
{
Oid dboid = 0;
bool invalidate_global = false;
@@ -1251,10 +1190,6 @@ CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple)
* This is used in places that need to force relcache rebuild but aren't
* changing any of the tuples recognized as contributors to the relcache
* entry by PrepareForTupleInvalidation. (An example is dropping an index.)
- * We assume in particular that relfilenode/reltablespace aren't changing
- * (so the rd_node value is still good).
- *
- * XXX most callers of this probably don't need to force an smgr flush.
*/
void
CacheInvalidateRelcache(Relation relation)
@@ -1269,7 +1204,6 @@ CacheInvalidateRelcache(Relation relation)
databaseId = MyDatabaseId;
RegisterRelcacheInvalidation(databaseId, relationId);
- RegisterSmgrInvalidation(relation->rd_node);
}
/*
@@ -1282,22 +1216,13 @@ CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Form_pg_class classtup = (Form_pg_class) GETSTRUCT(classTuple);
Oid databaseId;
Oid relationId;
- RelFileNode rnode;
relationId = HeapTupleGetOid(classTuple);
if (classtup->relisshared)
databaseId = InvalidOid;
else
databaseId = MyDatabaseId;
- if (classtup->reltablespace)
- rnode.spcNode = classtup->reltablespace;
- else
- rnode.spcNode = MyDatabaseTableSpace;
- rnode.dbNode = databaseId;
- rnode.relNode = classtup->relfilenode;
-
RegisterRelcacheInvalidation(databaseId, relationId);
- RegisterSmgrInvalidation(rnode);
}
/*
@@ -1320,6 +1245,39 @@ CacheInvalidateRelcacheByRelid(Oid relid)
ReleaseSysCache(tup);
}
+
+/*
+ * CacheInvalidateSmgr
+ * Register invalidation of smgr references to a physical relation.
+ *
+ * Sending this type of invalidation msg forces other backends to close open
+ * smgr entries for the rel. This should be done to flush dangling open-file
+ * references when the physical rel is being dropped or truncated. Because
+ * these are nontransactional (i.e., not-rollback-able) operations, we just
+ * send the inval message immediately without any queuing.
+ *
+ * Note: in most cases there will have been a relcache flush issued against
+ * the rel at the logical level. We need a separate smgr-level flush because
+ * it is possible for backends to have open smgr entries for rels they don't
+ * have a relcache entry for, e.g. because the only thing they ever did with
+ * the rel is write out dirty shared buffers.
+ *
+ * Note: because these messages are nontransactional, they won't be captured
+ * in commit/abort WAL entries. Instead, calls to CacheInvalidateSmgr()
+ * should happen in low-level smgr.c routines, which are executed while
+ * replaying WAL as well as when creating it.
+ */
+void
+CacheInvalidateSmgr(RelFileNode rnode)
+{
+ SharedInvalidationMessage msg;
+
+ msg.sm.id = SHAREDINVALSMGR_ID;
+ msg.sm.rnode = rnode;
+ SendSharedInvalidMessages(&msg, 1);
+}
+
+
/*
* CacheRegisterSyscacheCallback
* Register the specified function to be called for all future