Skip to content
Snippets Groups Projects
Commit 88ef7067 authored by Tom Lane's avatar Tom Lane
Browse files

Add cache invalidation callback hooks.

parent 8d615763
No related branches found
No related tags found
No related merge requests found
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.50 2002/04/12 20:38:28 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.51 2002/04/29 22:14:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -109,8 +109,7 @@ typedef struct InvalidationListHeader ...@@ -109,8 +109,7 @@ typedef struct InvalidationListHeader
InvalidationChunk *rclist; /* list of chunks holding relcache msgs */ InvalidationChunk *rclist; /* list of chunks holding relcache msgs */
} InvalidationListHeader; } InvalidationListHeader;
/* /*----------------
* ----------------
* Invalidation info is divided into two lists: * Invalidation info is divided into two lists:
* 1) events so far in current command, not yet reflected to caches. * 1) events so far in current command, not yet reflected to caches.
* 2) events in previous commands of current transaction; these have * 2) events in previous commands of current transaction; these have
...@@ -121,7 +120,7 @@ typedef struct InvalidationListHeader ...@@ -121,7 +120,7 @@ typedef struct InvalidationListHeader
* The relcache-file-invalidated flag can just be a simple boolean, * The relcache-file-invalidated flag can just be a simple boolean,
* since we only act on it at transaction commit; we don't care which * since we only act on it at transaction commit; we don't care which
* command of the transaction set it. * command of the transaction set it.
* ---------------- *----------------
*/ */
/* head of current-command event list */ /* head of current-command event list */
...@@ -132,6 +131,22 @@ static InvalidationListHeader PriorCmdInvalidMsgs; ...@@ -132,6 +131,22 @@ static InvalidationListHeader PriorCmdInvalidMsgs;
static bool RelcacheInitFileInval; /* init file must be invalidated? */ static bool RelcacheInitFileInval; /* init file must be invalidated? */
/*
* Dynamically-registered callback functions. Current implementation
* assumes there won't be very many of these at once; could improve if needed.
*/
#define MAX_CACHE_CALLBACKS 20
static struct CACHECALLBACK
{
int16 id; /* cache number or SHAREDINVALRELCACHE_ID */
CacheCallbackFunction function;
Datum arg;
} cache_callback_list[MAX_CACHE_CALLBACKS];
static int cache_callback_count = 0;
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* Invalidation list support functions * Invalidation list support functions
...@@ -398,17 +413,39 @@ RegisterRelcacheInvalidation(Oid dbId, Oid relId) ...@@ -398,17 +413,39 @@ RegisterRelcacheInvalidation(Oid dbId, Oid relId)
static void static void
LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg) LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
{ {
int i;
if (msg->id >= 0) if (msg->id >= 0)
{ {
if (msg->cc.dbId == MyDatabaseId || msg->cc.dbId == 0) if (msg->cc.dbId == MyDatabaseId || msg->cc.dbId == 0)
{
CatalogCacheIdInvalidate(msg->cc.id, CatalogCacheIdInvalidate(msg->cc.id,
msg->cc.hashValue, msg->cc.hashValue,
&msg->cc.tuplePtr); &msg->cc.tuplePtr);
for (i = 0; i < cache_callback_count; i++)
{
struct CACHECALLBACK *ccitem = cache_callback_list + i;
if (ccitem->id == msg->cc.id)
(*ccitem->function) (ccitem->arg, InvalidOid);
}
}
} }
else if (msg->id == SHAREDINVALRELCACHE_ID) else if (msg->id == SHAREDINVALRELCACHE_ID)
{ {
if (msg->rc.dbId == MyDatabaseId || msg->rc.dbId == 0) if (msg->rc.dbId == MyDatabaseId || msg->rc.dbId == 0)
{
RelationIdInvalidateRelationCacheByRelationId(msg->rc.relId); RelationIdInvalidateRelationCacheByRelationId(msg->rc.relId);
for (i = 0; i < cache_callback_count; i++)
{
struct CACHECALLBACK *ccitem = cache_callback_list + i;
if (ccitem->id == SHAREDINVALRELCACHE_ID)
(*ccitem->function) (ccitem->arg, msg->rc.relId);
}
}
} }
else else
{ {
...@@ -431,8 +468,17 @@ LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg) ...@@ -431,8 +468,17 @@ LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
static void static void
InvalidateSystemCaches(void) InvalidateSystemCaches(void)
{ {
int i;
ResetCatalogCaches(); ResetCatalogCaches();
RelationCacheInvalidate(); RelationCacheInvalidate();
for (i = 0; i < cache_callback_count; i++)
{
struct CACHECALLBACK *ccitem = cache_callback_list + i;
(*ccitem->function) (ccitem->arg, InvalidOid);
}
} }
/* /*
...@@ -640,3 +686,51 @@ CacheInvalidateRelcache(Oid relationId) ...@@ -640,3 +686,51 @@ CacheInvalidateRelcache(Oid relationId)
/* See KLUGE ALERT in PrepareForTupleInvalidation */ /* See KLUGE ALERT in PrepareForTupleInvalidation */
RegisterRelcacheInvalidation(MyDatabaseId, relationId); RegisterRelcacheInvalidation(MyDatabaseId, relationId);
} }
/*
* CacheRegisterSyscacheCallback
* Register the specified function to be called for all future
* invalidation events in the specified cache.
*
* NOTE: currently, the OID argument to the callback routine is not
* provided for syscache callbacks; the routine doesn't really get any
* useful info as to exactly what changed. It should treat every call
* as a "cache flush" request.
*/
void
CacheRegisterSyscacheCallback(int cacheid,
CacheCallbackFunction func,
Datum arg)
{
if (cache_callback_count >= MAX_CACHE_CALLBACKS)
elog(FATAL, "Out of cache_callback_list slots");
cache_callback_list[cache_callback_count].id = cacheid;
cache_callback_list[cache_callback_count].function = func;
cache_callback_list[cache_callback_count].arg = arg;
++cache_callback_count;
}
/*
* CacheRegisterRelcacheCallback
* Register the specified function to be called for all future
* relcache invalidation events. The OID of the relation being
* invalidated will be passed to the function.
*
* NOTE: InvalidOid will be passed if a cache reset request is received.
* In this case the called routines should flush all cached state.
*/
void
CacheRegisterRelcacheCallback(CacheCallbackFunction func,
Datum arg)
{
if (cache_callback_count >= MAX_CACHE_CALLBACKS)
elog(FATAL, "Out of cache_callback_list slots");
cache_callback_list[cache_callback_count].id = SHAREDINVALRELCACHE_ID;
cache_callback_list[cache_callback_count].function = func;
cache_callback_list[cache_callback_count].arg = arg;
++cache_callback_count;
}
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: inval.h,v 1.24 2002/03/03 17:47:56 tgl Exp $ * $Id: inval.h,v 1.25 2002/04/29 22:14:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
#include "access/htup.h" #include "access/htup.h"
typedef void (*CacheCallbackFunction) (Datum arg, Oid relid);
extern void AcceptInvalidationMessages(void); extern void AcceptInvalidationMessages(void);
extern void AtEOXactInvalidationMessages(bool isCommit); extern void AtEOXactInvalidationMessages(bool isCommit);
...@@ -27,4 +30,11 @@ extern void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple); ...@@ -27,4 +30,11 @@ extern void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple);
extern void CacheInvalidateRelcache(Oid relationId); extern void CacheInvalidateRelcache(Oid relationId);
extern void CacheRegisterSyscacheCallback(int cacheid,
CacheCallbackFunction func,
Datum arg);
extern void CacheRegisterRelcacheCallback(CacheCallbackFunction func,
Datum arg);
#endif /* INVAL_H */ #endif /* INVAL_H */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment