aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/relcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r--src/backend/utils/cache/relcache.c49
1 files changed, 38 insertions, 11 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index d7fd83775b1..b95a233bac7 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.168 2002/07/20 05:16:58 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.169 2002/08/02 22:36:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1968,34 +1968,61 @@ RelationCacheInvalidate(void)
}
/*
- * RelationCacheAbort
+ * AtEOXactRelationCache
*
- * Clean up the relcache at transaction abort.
+ * Clean up the relcache at transaction commit or abort.
*
- * What we need to do here is reset relcache entry ref counts to
- * their normal not-in-a-transaction state. A ref count may be
+ * During transaction abort, we must reset relcache entry ref counts
+ * to their normal not-in-a-transaction state. A ref count may be
* too high because some routine was exited by elog() between
* incrementing and decrementing the count.
*
- * XXX Maybe we should do this at transaction commit, too, in case
- * someone forgets to decrement a refcount in a non-error path?
+ * During commit, we should not have to do this, but it's useful to
+ * check that the counts are correct to catch missed relcache closes.
+ * Since that's basically a debugging thing, only pay the cost when
+ * assert checking is enabled.
+ *
+ * In bootstrap mode, forget the debugging checks --- the bootstrap code
+ * expects relations to stay open across start/commit transaction calls.
*/
void
-RelationCacheAbort(void)
+AtEOXactRelationCache(bool commit)
{
HASH_SEQ_STATUS status;
RelIdCacheEnt *idhentry;
+#ifdef USE_ASSERT_CHECKING
+ if (commit && IsBootstrapProcessingMode())
+ return;
+#else
+ if (commit)
+ return;
+#endif
+
hash_seq_init(&status, RelationIdCache);
while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
{
Relation relation = idhentry->reldesc;
+ int expected_refcnt;
+
+ expected_refcnt = relation->rd_isnailed ? 1 : 0;
- if (relation->rd_isnailed)
- RelationSetReferenceCount(relation, 1);
+ if (commit)
+ {
+ if (relation->rd_refcnt != expected_refcnt)
+ {
+ elog(WARNING, "Relcache reference leak: relation \"%s\" has refcnt %d instead of %d",
+ RelationGetRelationName(relation),
+ relation->rd_refcnt, expected_refcnt);
+ RelationSetReferenceCount(relation, expected_refcnt);
+ }
+ }
else
- RelationSetReferenceCount(relation, 0);
+ {
+ /* abort case, just reset it quietly */
+ RelationSetReferenceCount(relation, expected_refcnt);
+ }
}
}