Commit b5282aa8 authored by Tom Lane's avatar Tom Lane

Revise sinval code to remove no-longer-used tuple TID from inval messages.

This requires adjusting the API for syscache callback functions: they now
get a hash value, not a TID, to identify the target tuple.  Most of them
weren't paying any attention to that argument anyway, but plancache did
require a small amount of fixing.

Also, improve performance a trifle by avoiding sending duplicate inval
messages when a heap_update isn't changing the catcache lookup columns.
parent 632ae682
...@@ -2028,7 +2028,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, ...@@ -2028,7 +2028,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
* the heaptup data structure is all in local memory, not in the shared * the heaptup data structure is all in local memory, not in the shared
* buffer. * buffer.
*/ */
CacheInvalidateHeapTuple(relation, heaptup); CacheInvalidateHeapTuple(relation, heaptup, NULL);
pgstat_count_heap_insert(relation); pgstat_count_heap_insert(relation);
...@@ -2354,7 +2354,7 @@ l1: ...@@ -2354,7 +2354,7 @@ l1:
* boundary. We have to do this before releasing the buffer because we * boundary. We have to do this before releasing the buffer because we
* need to look at the contents of the tuple. * need to look at the contents of the tuple.
*/ */
CacheInvalidateHeapTuple(relation, &tp); CacheInvalidateHeapTuple(relation, &tp, NULL);
/* Now we can release the buffer */ /* Now we can release the buffer */
ReleaseBuffer(buffer); ReleaseBuffer(buffer);
...@@ -2930,10 +2930,13 @@ l2: ...@@ -2930,10 +2930,13 @@ l2:
/* /*
* Mark old tuple for invalidation from system caches at next command * Mark old tuple for invalidation from system caches at next command
* boundary. We have to do this before releasing the buffer because we * boundary, and mark the new tuple for invalidation in case we abort.
* need to look at the contents of the tuple. * We have to do this before releasing the buffer because oldtup is in
* the buffer. (heaptup is all in local memory, but it's necessary to
* process both tuple versions in one call to inval.c so we can avoid
* redundant sinval messages.)
*/ */
CacheInvalidateHeapTuple(relation, &oldtup); CacheInvalidateHeapTuple(relation, &oldtup, heaptup);
/* Now we can release the buffer(s) */ /* Now we can release the buffer(s) */
if (newbuf != buffer) if (newbuf != buffer)
...@@ -2944,14 +2947,6 @@ l2: ...@@ -2944,14 +2947,6 @@ l2:
if (BufferIsValid(vmbuffer)) if (BufferIsValid(vmbuffer))
ReleaseBuffer(vmbuffer); ReleaseBuffer(vmbuffer);
/*
* If new tuple is cachable, mark it for invalidation from the caches in
* case we abort. Note it is OK to do this after releasing the buffer,
* because the heaptup data structure is all in local memory, not in the
* shared buffer.
*/
CacheInvalidateHeapTuple(relation, heaptup);
/* /*
* Release the lmgr tuple lock, if we had it. * Release the lmgr tuple lock, if we had it.
*/ */
...@@ -3659,9 +3654,14 @@ heap_inplace_update(Relation relation, HeapTuple tuple) ...@@ -3659,9 +3654,14 @@ heap_inplace_update(Relation relation, HeapTuple tuple)
UnlockReleaseBuffer(buffer); UnlockReleaseBuffer(buffer);
/* Send out shared cache inval if necessary */ /*
* Send out shared cache inval if necessary. Note that because we only
* pass the new version of the tuple, this mustn't be used for any
* operations that could change catcache lookup keys. But we aren't
* bothering with index updates either, so that's true a fortiori.
*/
if (!IsBootstrapProcessingMode()) if (!IsBootstrapProcessingMode())
CacheInvalidateHeapTuple(relation, tuple); CacheInvalidateHeapTuple(relation, tuple, NULL);
} }
......
...@@ -192,7 +192,7 @@ static void recomputeNamespacePath(void); ...@@ -192,7 +192,7 @@ static void recomputeNamespacePath(void);
static void InitTempTableNamespace(void); static void InitTempTableNamespace(void);
static void RemoveTempRelations(Oid tempNamespaceId); static void RemoveTempRelations(Oid tempNamespaceId);
static void RemoveTempRelationsCallback(int code, Datum arg); static void RemoveTempRelationsCallback(int code, Datum arg);
static void NamespaceCallback(Datum arg, int cacheid, ItemPointer tuplePtr); static void NamespaceCallback(Datum arg, int cacheid, uint32 hashvalue);
static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames, static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
int **argnumbers); int **argnumbers);
...@@ -3750,7 +3750,7 @@ InitializeSearchPath(void) ...@@ -3750,7 +3750,7 @@ InitializeSearchPath(void)
* Syscache inval callback function * Syscache inval callback function
*/ */
static void static void
NamespaceCallback(Datum arg, int cacheid, ItemPointer tuplePtr) NamespaceCallback(Datum arg, int cacheid, uint32 hashvalue)
{ {
/* Force search path to be recomputed on next use */ /* Force search path to be recomputed on next use */
baseSearchPathValid = false; baseSearchPathValid = false;
......
...@@ -964,8 +964,7 @@ _copyPlanInvalItem(PlanInvalItem *from) ...@@ -964,8 +964,7 @@ _copyPlanInvalItem(PlanInvalItem *from)
PlanInvalItem *newnode = makeNode(PlanInvalItem); PlanInvalItem *newnode = makeNode(PlanInvalItem);
COPY_SCALAR_FIELD(cacheId); COPY_SCALAR_FIELD(cacheId);
/* tupleId isn't really a "scalar", but this works anyway */ COPY_SCALAR_FIELD(hashValue);
COPY_SCALAR_FIELD(tupleId);
return newnode; return newnode;
} }
......
...@@ -845,9 +845,7 @@ _outPlanInvalItem(StringInfo str, PlanInvalItem *node) ...@@ -845,9 +845,7 @@ _outPlanInvalItem(StringInfo str, PlanInvalItem *node)
WRITE_NODE_TYPE("PLANINVALITEM"); WRITE_NODE_TYPE("PLANINVALITEM");
WRITE_INT_FIELD(cacheId); WRITE_INT_FIELD(cacheId);
appendStringInfo(str, " :tupleId (%u,%u)", WRITE_UINT_FIELD(hashValue);
ItemPointerGetBlockNumber(&node->tupleId),
ItemPointerGetOffsetNumber(&node->tupleId));
} }
/***************************************************************************** /*****************************************************************************
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
#include "postgres.h" #include "postgres.h"
#include "access/hash.h"
#include "access/transam.h" #include "access/transam.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
...@@ -1751,25 +1752,21 @@ record_plan_function_dependency(PlannerGlobal *glob, Oid funcid) ...@@ -1751,25 +1752,21 @@ record_plan_function_dependency(PlannerGlobal *glob, Oid funcid)
*/ */
if (funcid >= (Oid) FirstBootstrapObjectId) if (funcid >= (Oid) FirstBootstrapObjectId)
{ {
HeapTuple func_tuple; PlanInvalItem *inval_item = makeNode(PlanInvalItem);
PlanInvalItem *inval_item;
func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
if (!HeapTupleIsValid(func_tuple))
elog(ERROR, "cache lookup failed for function %u", funcid);
inval_item = makeNode(PlanInvalItem);
/* /*
* It would work to use any syscache on pg_proc, but plancache.c * It would work to use any syscache on pg_proc, but the easiest is
* expects us to use PROCOID. * PROCOID since we already have the function's OID at hand. Note
* that plancache.c knows we use PROCOID. Also, we're perhaps
* assuming more than we should about how CatalogCacheComputeHashValue
* computes hash values...
*/ */
inval_item->cacheId = PROCOID; inval_item->cacheId = PROCOID;
inval_item->tupleId = func_tuple->t_self; inval_item->hashValue =
DatumGetUInt32(DirectFunctionCall1(hashoid,
ObjectIdGetDatum(funcid)));
glob->invalItems = lappend(glob->invalItems, inval_item); glob->invalItems = lappend(glob->invalItems, inval_item);
ReleaseSysCache(func_tuple);
} }
} }
......
...@@ -101,7 +101,7 @@ static bool list_member_strip(List *list, Expr *datum); ...@@ -101,7 +101,7 @@ static bool list_member_strip(List *list, Expr *datum);
static bool btree_predicate_proof(Expr *predicate, Node *clause, static bool btree_predicate_proof(Expr *predicate, Node *clause,
bool refute_it); bool refute_it);
static Oid get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it); static Oid get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it);
static void InvalidateOprProofCacheCallBack(Datum arg, int cacheid, ItemPointer tuplePtr); static void InvalidateOprProofCacheCallBack(Datum arg, int cacheid, uint32 hashvalue);
/* /*
...@@ -1738,7 +1738,7 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it) ...@@ -1738,7 +1738,7 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
* Callback for pg_amop inval events * Callback for pg_amop inval events
*/ */
static void static void
InvalidateOprProofCacheCallBack(Datum arg, int cacheid, ItemPointer tuplePtr) InvalidateOprProofCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
{ {
HASH_SEQ_STATUS status; HASH_SEQ_STATUS status;
OprProofCacheEntry *hentry; OprProofCacheEntry *hentry;
......
...@@ -79,7 +79,7 @@ static bool make_oper_cache_key(OprCacheKey *key, List *opname, ...@@ -79,7 +79,7 @@ static bool make_oper_cache_key(OprCacheKey *key, List *opname,
Oid ltypeId, Oid rtypeId); Oid ltypeId, Oid rtypeId);
static Oid find_oper_cache_entry(OprCacheKey *key); static Oid find_oper_cache_entry(OprCacheKey *key);
static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid); static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid);
static void InvalidateOprCacheCallBack(Datum arg, int cacheid, ItemPointer tuplePtr); static void InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue);
/* /*
...@@ -1104,7 +1104,7 @@ make_oper_cache_entry(OprCacheKey *key, Oid opr_oid) ...@@ -1104,7 +1104,7 @@ make_oper_cache_entry(OprCacheKey *key, Oid opr_oid)
* Callback for pg_operator and pg_cast inval events * Callback for pg_operator and pg_cast inval events
*/ */
static void static void
InvalidateOprCacheCallBack(Datum arg, int cacheid, ItemPointer tuplePtr) InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
{ {
HASH_SEQ_STATUS status; HASH_SEQ_STATUS status;
OprCacheEntry *hentry; OprCacheEntry *hentry;
......
...@@ -112,7 +112,7 @@ static AclMode convert_tablespace_priv_string(text *priv_type_text); ...@@ -112,7 +112,7 @@ static AclMode convert_tablespace_priv_string(text *priv_type_text);
static AclMode convert_role_priv_string(text *priv_type_text); static AclMode convert_role_priv_string(text *priv_type_text);
static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode); static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode);
static void RoleMembershipCacheCallback(Datum arg, int cacheid, ItemPointer tuplePtr); static void RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue);
static Oid get_role_oid_or_public(const char *rolname); static Oid get_role_oid_or_public(const char *rolname);
...@@ -4355,7 +4355,7 @@ initialize_acl(void) ...@@ -4355,7 +4355,7 @@ initialize_acl(void)
* Syscache inval callback function * Syscache inval callback function
*/ */
static void static void
RoleMembershipCacheCallback(Datum arg, int cacheid, ItemPointer tuplePtr) RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
{ {
/* Force membership caches to be recomputed on next use */ /* Force membership caches to be recomputed on next use */
cached_privs_role = InvalidOid; cached_privs_role = InvalidOid;
......
...@@ -53,7 +53,7 @@ typedef struct ...@@ -53,7 +53,7 @@ typedef struct
* query execution), this seems OK. * query execution), this seems OK.
*/ */
static void static void
InvalidateAttoptCacheCallback(Datum arg, int cacheid, ItemPointer tuplePtr) InvalidateAttoptCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
{ {
HASH_SEQ_STATUS status; HASH_SEQ_STATUS status;
AttoptCacheEntry *attopt; AttoptCacheEntry *attopt;
......
...@@ -435,21 +435,14 @@ CatCacheRemoveCList(CatCache *cache, CatCList *cl) ...@@ -435,21 +435,14 @@ CatCacheRemoveCList(CatCache *cache, CatCList *cl)
* target tuple that has to be invalidated has a different TID than it * target tuple that has to be invalidated has a different TID than it
* did when the event was created. So now we just compare hash values and * did when the event was created. So now we just compare hash values and
* accept the small risk of unnecessary invalidations due to false matches. * accept the small risk of unnecessary invalidations due to false matches.
* (The ItemPointer argument is therefore useless and should get removed.)
* *
* This routine is only quasi-public: it should only be used by inval.c. * This routine is only quasi-public: it should only be used by inval.c.
*/ */
void void
CatalogCacheIdInvalidate(int cacheId, CatalogCacheIdInvalidate(int cacheId, uint32 hashValue)
uint32 hashValue,
ItemPointer pointer)
{ {
CatCache *ccp; CatCache *ccp;
/*
* sanity checks
*/
Assert(ItemPointerIsValid(pointer));
CACHE1_elog(DEBUG2, "CatalogCacheIdInvalidate: called"); CACHE1_elog(DEBUG2, "CatalogCacheIdInvalidate: called");
/* /*
...@@ -699,7 +692,7 @@ CatalogCacheFlushCatalog(Oid catId) ...@@ -699,7 +692,7 @@ CatalogCacheFlushCatalog(Oid catId)
ResetCatalogCache(cache); ResetCatalogCache(cache);
/* Tell inval.c to call syscache callbacks for this cache */ /* Tell inval.c to call syscache callbacks for this cache */
CallSyscacheCallbacks(cache->id, NULL); CallSyscacheCallbacks(cache->id, 0);
} }
} }
...@@ -1708,11 +1701,16 @@ build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys) ...@@ -1708,11 +1701,16 @@ build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys)
* The lists of tuples that need to be flushed are kept by inval.c. This * The lists of tuples that need to be flushed are kept by inval.c. This
* routine is a helper routine for inval.c. Given a tuple belonging to * routine is a helper routine for inval.c. Given a tuple belonging to
* the specified relation, find all catcaches it could be in, compute the * the specified relation, find all catcaches it could be in, compute the
* correct hash value for each such catcache, and call the specified function * correct hash value for each such catcache, and call the specified
* to record the cache id, hash value, and tuple ItemPointer in inval.c's * function to record the cache id and hash value in inval.c's lists.
* lists. CatalogCacheIdInvalidate will be called later, if appropriate, * CatalogCacheIdInvalidate will be called later, if appropriate,
* using the recorded information. * using the recorded information.
* *
* For an insert or delete, tuple is the target tuple and newtuple is NULL.
* For an update, we are called just once, with tuple being the old tuple
* version and newtuple the new version. We should make two list entries
* if the tuple's hash value changed, but only one if it didn't.
*
* Note that it is irrelevant whether the given tuple is actually loaded * Note that it is irrelevant whether the given tuple is actually loaded
* into the catcache at the moment. Even if it's not there now, it might * into the catcache at the moment. Even if it's not there now, it might
* be by the end of the command, or there might be a matching negative entry * be by the end of the command, or there might be a matching negative entry
...@@ -1727,7 +1725,8 @@ build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys) ...@@ -1727,7 +1725,8 @@ build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys)
void void
PrepareToInvalidateCacheTuple(Relation relation, PrepareToInvalidateCacheTuple(Relation relation,
HeapTuple tuple, HeapTuple tuple,
void (*function) (int, uint32, ItemPointer, Oid)) HeapTuple newtuple,
void (*function) (int, uint32, Oid))
{ {
CatCache *ccp; CatCache *ccp;
Oid reloid; Oid reloid;
...@@ -1747,13 +1746,16 @@ PrepareToInvalidateCacheTuple(Relation relation, ...@@ -1747,13 +1746,16 @@ PrepareToInvalidateCacheTuple(Relation relation,
/* ---------------- /* ----------------
* for each cache * for each cache
* if the cache contains tuples from the specified relation * if the cache contains tuples from the specified relation
* compute the tuple's hash value in this cache, * compute the tuple's hash value(s) in this cache,
* and call the passed function to register the information. * and call the passed function to register the information.
* ---------------- * ----------------
*/ */
for (ccp = CacheHdr->ch_caches; ccp; ccp = ccp->cc_next) for (ccp = CacheHdr->ch_caches; ccp; ccp = ccp->cc_next)
{ {
uint32 hashvalue;
Oid dbid;
if (ccp->cc_reloid != reloid) if (ccp->cc_reloid != reloid)
continue; continue;
...@@ -1761,10 +1763,20 @@ PrepareToInvalidateCacheTuple(Relation relation, ...@@ -1761,10 +1763,20 @@ PrepareToInvalidateCacheTuple(Relation relation,
if (ccp->cc_tupdesc == NULL) if (ccp->cc_tupdesc == NULL)
CatalogCacheInitializeCache(ccp); CatalogCacheInitializeCache(ccp);
(*function) (ccp->id, hashvalue = CatalogCacheComputeTupleHashValue(ccp, tuple);
CatalogCacheComputeTupleHashValue(ccp, tuple), dbid = ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId;
&tuple->t_self,
ccp->cc_relisshared ? (Oid) 0 : MyDatabaseId); (*function) (ccp->id, hashvalue, dbid);
if (newtuple)
{
uint32 newhashvalue;
newhashvalue = CatalogCacheComputeTupleHashValue(ccp, newtuple);
if (newhashvalue != hashvalue)
(*function) (ccp->id, newhashvalue, dbid);
}
} }
} }
......
This diff is collapsed.
...@@ -71,8 +71,8 @@ static void ScanQueryForLocks(Query *parsetree, bool acquire); ...@@ -71,8 +71,8 @@ static void ScanQueryForLocks(Query *parsetree, bool acquire);
static bool ScanQueryWalker(Node *node, bool *acquire); static bool ScanQueryWalker(Node *node, bool *acquire);
static bool plan_list_is_transient(List *stmt_list); static bool plan_list_is_transient(List *stmt_list);
static void PlanCacheRelCallback(Datum arg, Oid relid); static void PlanCacheRelCallback(Datum arg, Oid relid);
static void PlanCacheFuncCallback(Datum arg, int cacheid, ItemPointer tuplePtr); static void PlanCacheFuncCallback(Datum arg, int cacheid, uint32 hashvalue);
static void PlanCacheSysCallback(Datum arg, int cacheid, ItemPointer tuplePtr); static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue);
/* /*
...@@ -1029,14 +1029,14 @@ PlanCacheRelCallback(Datum arg, Oid relid) ...@@ -1029,14 +1029,14 @@ PlanCacheRelCallback(Datum arg, Oid relid)
* PlanCacheFuncCallback * PlanCacheFuncCallback
* Syscache inval callback function for PROCOID cache * Syscache inval callback function for PROCOID cache
* *
* Invalidate all plans mentioning the given catalog entry, or all plans * Invalidate all plans mentioning the object with the specified hash value,
* mentioning any member of this cache if tuplePtr == NULL. * or all plans mentioning any member of this cache if hashvalue == 0.
* *
* Note that the coding would support use for multiple caches, but right * Note that the coding would support use for multiple caches, but right
* now only user-defined functions are tracked this way. * now only user-defined functions are tracked this way.
*/ */
static void static void
PlanCacheFuncCallback(Datum arg, int cacheid, ItemPointer tuplePtr) PlanCacheFuncCallback(Datum arg, int cacheid, uint32 hashvalue)
{ {
ListCell *lc1; ListCell *lc1;
...@@ -1060,8 +1060,8 @@ PlanCacheFuncCallback(Datum arg, int cacheid, ItemPointer tuplePtr) ...@@ -1060,8 +1060,8 @@ PlanCacheFuncCallback(Datum arg, int cacheid, ItemPointer tuplePtr)
if (item->cacheId != cacheid) if (item->cacheId != cacheid)
continue; continue;
if (tuplePtr == NULL || if (hashvalue == 0 ||
ItemPointerEquals(tuplePtr, &item->tupleId)) item->hashValue == hashvalue)
{ {
/* Invalidate the plan! */ /* Invalidate the plan! */
plan->dead = true; plan->dead = true;
...@@ -1086,8 +1086,8 @@ PlanCacheFuncCallback(Datum arg, int cacheid, ItemPointer tuplePtr) ...@@ -1086,8 +1086,8 @@ PlanCacheFuncCallback(Datum arg, int cacheid, ItemPointer tuplePtr)
if (item->cacheId != cacheid) if (item->cacheId != cacheid)
continue; continue;
if (tuplePtr == NULL || if (hashvalue == 0 ||
ItemPointerEquals(tuplePtr, &item->tupleId)) item->hashValue == hashvalue)
{ {
/* Invalidate the plan! */ /* Invalidate the plan! */
plan->dead = true; plan->dead = true;
...@@ -1108,7 +1108,7 @@ PlanCacheFuncCallback(Datum arg, int cacheid, ItemPointer tuplePtr) ...@@ -1108,7 +1108,7 @@ PlanCacheFuncCallback(Datum arg, int cacheid, ItemPointer tuplePtr)
* Just invalidate everything... * Just invalidate everything...
*/ */
static void static void
PlanCacheSysCallback(Datum arg, int cacheid, ItemPointer tuplePtr) PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue)
{ {
ResetPlanCache(); ResetPlanCache();
} }
......
...@@ -50,7 +50,7 @@ typedef struct ...@@ -50,7 +50,7 @@ typedef struct
* tablespaces, nor do we expect them to be frequently modified. * tablespaces, nor do we expect them to be frequently modified.
*/ */
static void static void
InvalidateTableSpaceCacheCallback(Datum arg, int cacheid, ItemPointer tuplePtr) InvalidateTableSpaceCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
{ {
HASH_SEQ_STATUS status; HASH_SEQ_STATUS status;
TableSpaceCacheEntry *spc; TableSpaceCacheEntry *spc;
......
...@@ -90,7 +90,7 @@ static Oid TSCurrentConfigCache = InvalidOid; ...@@ -90,7 +90,7 @@ static Oid TSCurrentConfigCache = InvalidOid;
* table address as the "arg". * table address as the "arg".
*/ */
static void static void
InvalidateTSCacheCallBack(Datum arg, int cacheid, ItemPointer tuplePtr) InvalidateTSCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
{ {
HTAB *hash = (HTAB *) DatumGetPointer(arg); HTAB *hash = (HTAB *) DatumGetPointer(arg);
HASH_SEQ_STATUS status; HASH_SEQ_STATUS status;
......
...@@ -36,7 +36,7 @@ static Oid last_roleid = InvalidOid; /* InvalidOid == cache not valid */ ...@@ -36,7 +36,7 @@ static Oid last_roleid = InvalidOid; /* InvalidOid == cache not valid */
static bool last_roleid_is_super = false; static bool last_roleid_is_super = false;
static bool roleid_callback_registered = false; static bool roleid_callback_registered = false;
static void RoleidCallback(Datum arg, int cacheid, ItemPointer tuplePtr); static void RoleidCallback(Datum arg, int cacheid, uint32 hashvalue);
/* /*
...@@ -96,11 +96,11 @@ superuser_arg(Oid roleid) ...@@ -96,11 +96,11 @@ superuser_arg(Oid roleid)
} }
/* /*
* UseridCallback * RoleidCallback
* Syscache inval callback function * Syscache inval callback function
*/ */
static void static void
RoleidCallback(Datum arg, int cacheid, ItemPointer tuplePtr) RoleidCallback(Datum arg, int cacheid, uint32 hashvalue)
{ {
/* Invalidate our local cache in case role's superuserness changed */ /* Invalidate our local cache in case role's superuserness changed */
last_roleid = InvalidOid; last_roleid = InvalidOid;
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include "access/sdir.h" #include "access/sdir.h"
#include "nodes/bitmapset.h" #include "nodes/bitmapset.h"
#include "nodes/primnodes.h" #include "nodes/primnodes.h"
#include "storage/itemptr.h"
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -793,13 +792,13 @@ typedef struct PlanRowMark ...@@ -793,13 +792,13 @@ typedef struct PlanRowMark
* relations are recorded as a simple list of OIDs, and everything else * relations are recorded as a simple list of OIDs, and everything else
* is represented as a list of PlanInvalItems. A PlanInvalItem is designed * is represented as a list of PlanInvalItems. A PlanInvalItem is designed
* to be used with the syscache invalidation mechanism, so it identifies a * to be used with the syscache invalidation mechanism, so it identifies a
* system catalog entry by cache ID and tuple TID. * system catalog entry by cache ID and hash value.
*/ */
typedef struct PlanInvalItem typedef struct PlanInvalItem
{ {
NodeTag type; NodeTag type;
int cacheId; /* a syscache ID, see utils/syscache.h */ int cacheId; /* a syscache ID, see utils/syscache.h */
ItemPointerData tupleId; /* TID of the object's catalog tuple */ uint32 hashValue; /* hash value of object's cache lookup key */
} PlanInvalItem; } PlanInvalItem;
#endif /* PLANNODES_H */ #endif /* PLANNODES_H */
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#ifndef SINVAL_H #ifndef SINVAL_H
#define SINVAL_H #define SINVAL_H
#include "storage/itemptr.h"
#include "storage/relfilenode.h" #include "storage/relfilenode.h"
...@@ -32,22 +31,17 @@ ...@@ -32,22 +31,17 @@
* *
* Catcache inval events are initially driven by detecting tuple inserts, * Catcache inval events are initially driven by detecting tuple inserts,
* updates and deletions in system catalogs (see CacheInvalidateHeapTuple). * updates and deletions in system catalogs (see CacheInvalidateHeapTuple).
* An update generates two inval events, one for the old tuple and one for * An update can generate two inval events, one for the old tuple and one for
* the new --- this is needed to get rid of both positive entries for the * the new, but this is reduced to one event if the tuple's hash key doesn't
* old tuple, and negative cache entries associated with the new tuple's * change. Note that the inval events themselves don't actually say whether
* cache key. (This could perhaps be optimized down to one event when the * the tuple is being inserted or deleted. Also, since we transmit only a
* cache key is not changing, but for now we don't bother to try.) Note that * hash key, there is a small risk of unnecessary invalidations due to chance
* the inval events themselves don't actually say whether the tuple is being * matches of hash keys.
* inserted or deleted.
* *
* Note that some system catalogs have multiple caches on them (with different * Note that some system catalogs have multiple caches on them (with different
* indexes). On detecting a tuple invalidation in such a catalog, separate * indexes). On detecting a tuple invalidation in such a catalog, separate
* catcache inval messages must be generated for each of its caches. The * catcache inval messages must be generated for each of its caches, since
* catcache inval messages carry the hash value for the target tuple, so * the hash keys will generally be different.
* that the catcache only needs to search one hash chain not all its chains,
* and so that negative cache entries can be recognized with good accuracy.
* (Of course this assumes that all the backends are using identical hashing
* code, but that should be OK.)
* *
* Catcache and relcache invalidations are transactional, and so are sent * Catcache and relcache invalidations are transactional, and so are sent
* to other backends upon commit. Internally to the generating backend, * to other backends upon commit. Internally to the generating backend,
...@@ -62,9 +56,7 @@ ...@@ -62,9 +56,7 @@
typedef struct typedef struct
{ {
/* note: field layout chosen with an eye to alignment concerns */
int8 id; /* cache ID --- must be first */ int8 id; /* cache ID --- must be first */
ItemPointerData tuplePtr; /* tuple identifier in cached relation */
Oid dbId; /* database ID, or 0 if a shared relation */ Oid dbId; /* database ID, or 0 if a shared relation */
uint32 hashValue; /* hash value of key for this catcache */ uint32 hashValue; /* hash value of key for this catcache */
} SharedInvalCatcacheMsg; } SharedInvalCatcacheMsg;
...@@ -91,6 +83,7 @@ typedef struct ...@@ -91,6 +83,7 @@ typedef struct
typedef struct typedef struct
{ {
/* note: field layout chosen to pack into 16 bytes */
int8 id; /* type field --- must be first */ int8 id; /* type field --- must be first */
int8 backend_hi; /* high bits of backend ID, if temprel */ int8 backend_hi; /* high bits of backend ID, if temprel */
uint16 backend_lo; /* low bits of backend ID, if temprel */ uint16 backend_lo; /* low bits of backend ID, if temprel */
......
...@@ -181,11 +181,11 @@ extern void ReleaseCatCacheList(CatCList *list); ...@@ -181,11 +181,11 @@ extern void ReleaseCatCacheList(CatCList *list);
extern void ResetCatalogCaches(void); extern void ResetCatalogCaches(void);
extern void CatalogCacheFlushCatalog(Oid catId); extern void CatalogCacheFlushCatalog(Oid catId);
extern void CatalogCacheIdInvalidate(int cacheId, uint32 hashValue, extern void CatalogCacheIdInvalidate(int cacheId, uint32 hashValue);
ItemPointer pointer);
extern void PrepareToInvalidateCacheTuple(Relation relation, extern void PrepareToInvalidateCacheTuple(Relation relation,
HeapTuple tuple, HeapTuple tuple,
void (*function) (int, uint32, ItemPointer, Oid)); HeapTuple newtuple,
void (*function) (int, uint32, Oid));
extern void PrintCatCacheLeakWarning(HeapTuple tuple); extern void PrintCatCacheLeakWarning(HeapTuple tuple);
extern void PrintCatCacheListLeakWarning(CatCList *list); extern void PrintCatCacheListLeakWarning(CatCList *list);
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include "utils/relcache.h" #include "utils/relcache.h"
typedef void (*SyscacheCallbackFunction) (Datum arg, int cacheid, ItemPointer tuplePtr); typedef void (*SyscacheCallbackFunction) (Datum arg, int cacheid, uint32 hashvalue);
typedef void (*RelcacheCallbackFunction) (Datum arg, Oid relid); typedef void (*RelcacheCallbackFunction) (Datum arg, Oid relid);
...@@ -39,7 +39,9 @@ extern void PostPrepare_Inval(void); ...@@ -39,7 +39,9 @@ extern void PostPrepare_Inval(void);
extern void CommandEndInvalidationMessages(void); extern void CommandEndInvalidationMessages(void);
extern void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple); extern void CacheInvalidateHeapTuple(Relation relation,
HeapTuple tuple,
HeapTuple newtuple);
extern void CacheInvalidateCatalog(Oid catalogId); extern void CacheInvalidateCatalog(Oid catalogId);
...@@ -60,7 +62,7 @@ extern void CacheRegisterSyscacheCallback(int cacheid, ...@@ -60,7 +62,7 @@ extern void CacheRegisterSyscacheCallback(int cacheid,
extern void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, extern void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func,
Datum arg); Datum arg);
extern void CallSyscacheCallbacks(int cacheid, ItemPointer tuplePtr); extern void CallSyscacheCallbacks(int cacheid, uint32 hashvalue);
extern void inval_twophase_postcommit(TransactionId xid, uint16 info, extern void inval_twophase_postcommit(TransactionId xid, uint16 info,
void *recdata, uint32 len); void *recdata, uint32 len);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment