⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inval.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * inval.c *	  POSTGRES cache invalidation dispatcher code. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.23.2.1 1999/08/02 05:25:00 scrappy Exp $ * * Note - this code is real crufty... * *------------------------------------------------------------------------- */#include "postgres.h"#include "catalog/catalog.h"#include "catalog/catname.h"#include "catalog/heap.h"#include "miscadmin.h"#include "storage/sinval.h"#include "utils/catcache.h"#include "utils/inval.h"#include "utils/relcache.h"static InvalidationEntry InvalidationEntryAllocate(uint16 size);static void LocalInvalidInvalidate(LocalInvalid invalid, void (*function) ());static LocalInvalid LocalInvalidRegister(LocalInvalid invalid,					 InvalidationEntry entry);static void getmyrelids(void);/* ---------------- *		private invalidation structures * ---------------- */typedef struct CatalogInvalidationData{	Index		cacheId;	Index		hashIndex;	ItemPointerData pointerData;} CatalogInvalidationData;typedef struct RelationInvalidationData{	Oid			relationId;	Oid			objectId;} RelationInvalidationData;typedef union AnyInvalidation{	CatalogInvalidationData catalog;	RelationInvalidationData relation;} AnyInvalidation;typedef struct InvalidationMessageData{	char		kind;	AnyInvalidation any;} InvalidationMessageData;typedef InvalidationMessageData *InvalidationMessage;/* ---------------- *		variables and macros * ---------------- */static LocalInvalid Invalid = EmptyLocalInvalid;		/* XXX global */Oid			MyRelationRelationId = InvalidOid;Oid			MyAttributeRelationId = InvalidOid;Oid			MyAMRelationId = InvalidOid;Oid			MyAMOPRelationId = InvalidOid;#define ValidateHacks() \	if (!OidIsValid(MyRelationRelationId)) getmyrelids()/* ---------------------------------------------------------------- *				"local" invalidation support functions * ---------------------------------------------------------------- *//* -------------------------------- *		InvalidationEntryAllocate *				Allocates an invalidation entry. * -------------------------------- */static InvalidationEntryInvalidationEntryAllocate(uint16 size){	InvalidationEntryData *entryDataP;	entryDataP = (InvalidationEntryData *)		malloc(sizeof(char *) + size);	/* XXX alignment */	entryDataP->nextP = NULL;	return (Pointer) &entryDataP->userData;}/* -------------------------------- *		LocalInvalidRegister *		   Returns a new local cache invalidation state containing a new entry. * -------------------------------- */static LocalInvalidLocalInvalidRegister(LocalInvalid invalid,					 InvalidationEntry entry){	Assert(PointerIsValid(entry));	((InvalidationUserData *) entry)->dataP[-1] =		(InvalidationUserData *) invalid;	return entry;}/* -------------------------------- *		LocalInvalidInvalidate *				Processes, then frees all entries in a local cache *				invalidation state. * -------------------------------- */static voidLocalInvalidInvalidate(LocalInvalid invalid, void (*function) ()){	InvalidationEntryData *entryDataP;	while (PointerIsValid(invalid))	{		entryDataP = (InvalidationEntryData *)			&((InvalidationUserData *) invalid)->dataP[-1];		if (PointerIsValid(function))			(*function) ((Pointer) &entryDataP->userData);		invalid = (Pointer) entryDataP->nextP;		/* help catch errors */		entryDataP->nextP = (InvalidationUserData *) NULL;		free((Pointer) entryDataP);	}}/* ---------------------------------------------------------------- *					  private support functions * ---------------------------------------------------------------- *//* -------------------------------- *		CacheIdRegisterLocalInvalid * -------------------------------- */#ifdef	INVALIDDEBUG#define CacheIdRegisterLocalInvalid_DEBUG1 \elog(DEBUG, "CacheIdRegisterLocalInvalid(%d, %d, [%d, %d])", \	 cacheId, hashIndex, ItemPointerGetBlockNumber(pointer), \	 ItemPointerGetOffsetNumber(pointer))#else#define CacheIdRegisterLocalInvalid_DEBUG1#endif	 /* INVALIDDEBUG */static voidCacheIdRegisterLocalInvalid(Index cacheId,							Index hashIndex,							ItemPointer pointer){	InvalidationMessage message;	/* ----------------	 *	debugging stuff	 * ----------------	 */	CacheIdRegisterLocalInvalid_DEBUG1;	/* ----------------	 *	create a message describing the system catalog tuple	 *	we wish to invalidate.	 * ----------------	 */	message = (InvalidationMessage)		InvalidationEntryAllocate(sizeof(InvalidationMessageData));	message->kind = 'c';	message->any.catalog.cacheId = cacheId;	message->any.catalog.hashIndex = hashIndex;	ItemPointerCopy(pointer, &message->any.catalog.pointerData);	/* ----------------	 *	Note: Invalid is a global variable	 * ----------------	 */	Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry) message);}/* -------------------------------- *		RelationIdRegisterLocalInvalid * -------------------------------- */static voidRelationIdRegisterLocalInvalid(Oid relationId, Oid objectId){	InvalidationMessage message;	/* ----------------	 *	debugging stuff	 * ----------------	 */#ifdef	INVALIDDEBUG	elog(DEBUG, "RelationRegisterLocalInvalid(%u, %u)", relationId,		 objectId);#endif	 /* defined(INVALIDDEBUG) */	/* ----------------	 *	create a message describing the relation descriptor	 *	we wish to invalidate.	 * ----------------	 */	message = (InvalidationMessage)		InvalidationEntryAllocate(sizeof(InvalidationMessageData));	message->kind = 'r';	message->any.relation.relationId = relationId;	message->any.relation.objectId = objectId;	/* ----------------	 *	Note: Invalid is a global variable	 * ----------------	 */	Invalid = LocalInvalidRegister(Invalid, (InvalidationEntry) message);}/* -------------------------------- *		getmyrelids * -------------------------------- */static voidgetmyrelids(){	MyRelationRelationId = RelnameFindRelid(RelationRelationName);	Assert(RelationRelationName != InvalidOid);	MyAttributeRelationId = RelnameFindRelid(AttributeRelationName);	Assert(AttributeRelationName != InvalidOid);	MyAMRelationId = RelnameFindRelid(AccessMethodRelationName);	Assert(MyAMRelationId != InvalidOid);	MyAMOPRelationId = RelnameFindRelid(AccessMethodOperatorRelationName);	Assert(MyAMOPRelationId != InvalidOid);}/* -------------------------------- *		CacheIdInvalidate * *		This routine can invalidate a tuple in a system catalog cache *		or a cached relation descriptor.  You pay your money and you *		take your chances... * -------------------------------- */#ifdef	INVALIDDEBUG#define CacheIdInvalidate_DEBUG1 \elog(DEBUG, "CacheIdInvalidate(%d, %d, 0x%x[%d])", cacheId, hashIndex,\	 pointer, ItemPointerIsValid(pointer))#else#define CacheIdInvalidate_DEBUG1#endif	 /* defined(INVALIDDEBUG) */static voidCacheIdInvalidate(Index cacheId,				  Index hashIndex,				  ItemPointer pointer){	/* ----------------	 *	assume that if the item pointer is valid, then we are	 *	invalidating an item in the specified system catalog cache.	 * ----------------	 */	if (ItemPointerIsValid(pointer))	{		CatalogCacheIdInvalidate(cacheId, hashIndex, pointer);		return;	}	CacheIdInvalidate_DEBUG1;	ValidateHacks();			/* XXX */	/* ----------------	 *	if the cacheId is the oid of any of the tuples in the	 *	following system relations, then assume we are invalidating	 *	a relation descriptor	 * ----------------	 */	if (cacheId == MyRelationRelationId)	{		RelationIdInvalidateRelationCacheByRelationId(hashIndex);		return;	}	if (cacheId == MyAttributeRelationId)	{		RelationIdInvalidateRelationCacheByRelationId(hashIndex);		return;	}	if (cacheId == MyAMRelationId)	{		RelationIdInvalidateRelationCacheByAccessMethodId(hashIndex);		return;	}	if (cacheId == MyAMOPRelationId)	{		RelationIdInvalidateRelationCacheByAccessMethodId(InvalidOid);		return;	}	/* ----------------	 *	Yow! the caller asked us to invalidate something else.	 * ----------------	 */	elog(FATAL, "CacheIdInvalidate: cacheId=%d relation id?", cacheId);}/* -------------------------------- *		ResetSystemCaches * *		this blows away all tuples in the system catalog caches and *		all the cached relation descriptors (and closes the files too). * -------------------------------- */static voidResetSystemCaches(){	ResetSystemCache();	RelationCacheInvalidate(false);}/* -------------------------------- *		InvalidationMessageRegisterSharedInvalid * -------------------------------- */#ifdef	INVALIDDEBUG#define InvalidationMessageRegisterSharedInvalid_DEBUG1 \elog(DEBUG,\	 "InvalidationMessageRegisterSharedInvalid(c, %d, %d, [%d, %d])",\	 message->any.catalog.cacheId,\	 message->any.catalog.hashIndex,\	 ItemPointerGetBlockNumber(&message->any.catalog.pointerData),\	 ItemPointerGetOffsetNumber(&message->any.catalog.pointerData))#define InvalidationMessageRegisterSharedInvalid_DEBUG2 \	 elog(DEBUG, \		  "InvalidationMessageRegisterSharedInvalid(r, %u, %u)", \		  message->any.relation.relationId, \		  message->any.relation.objectId)#else#define InvalidationMessageRegisterSharedInvalid_DEBUG1#define InvalidationMessageRegisterSharedInvalid_DEBUG2#endif	 /* INVALIDDEBUG */static voidInvalidationMessageRegisterSharedInvalid(InvalidationMessage message){	Assert(PointerIsValid(message));	switch (message->kind)	{		case 'c':				/* cached system catalog tuple */			InvalidationMessageRegisterSharedInvalid_DEBUG1;			RegisterSharedInvalid(message->any.catalog.cacheId,								  message->any.catalog.hashIndex,								  &message->any.catalog.pointerData);			break;		case 'r':				/* cached relation descriptor */			InvalidationMessageRegisterSharedInvalid_DEBUG2;			RegisterSharedInvalid(message->any.relation.relationId,								  message->any.relation.objectId,								  (ItemPointer) NULL);			break;		default:			elog(FATAL,				 "InvalidationMessageRegisterSharedInvalid: `%c' kind",				 message->kind);	}}/* -------------------------------- *		InvalidationMessageCacheInvalidate * -------------------------------- */#ifdef	INVALIDDEBUG#define InvalidationMessageCacheInvalidate_DEBUG1 \elog(DEBUG, "InvalidationMessageCacheInvalidate(c, %d, %d, [%d, %d])",\	 message->any.catalog.cacheId,\	 message->any.catalog.hashIndex,\	 ItemPointerGetBlockNumber(&message->any.catalog.pointerData),\	 ItemPointerGetOffsetNumber(&message->any.catalog.pointerData))#define InvalidationMessageCacheInvalidate_DEBUG2 \	 elog(DEBUG, "InvalidationMessageCacheInvalidate(r, %u, %u)", \		  message->any.relation.relationId, \		  message->any.relation.objectId)#else#define InvalidationMessageCacheInvalidate_DEBUG1#define InvalidationMessageCacheInvalidate_DEBUG2#endif	 /* defined(INVALIDDEBUG) */static voidInvalidationMessageCacheInvalidate(InvalidationMessage message){	Assert(PointerIsValid(message));	switch (message->kind)	{		case 'c':				/* cached system catalog tuple */			InvalidationMessageCacheInvalidate_DEBUG1;			CatalogCacheIdInvalidate(message->any.catalog.cacheId,									 message->any.catalog.hashIndex,									 &message->any.catalog.pointerData);			break;		case 'r':				/* cached relation descriptor */			InvalidationMessageCacheInvalidate_DEBUG2;			/* XXX ignore this--is this correct ??? */			break;		default:			elog(FATAL, "InvalidationMessageCacheInvalidate: `%c' kind",				 message->kind);	}}/* -------------------------------- *		RelationInvalidateRelationCache * -------------------------------- */static voidRelationInvalidateRelationCache(Relation relation,								HeapTuple tuple,								void (*function) ()){	Oid			relationId;	Oid			objectId = (Oid) 0;	/* ----------------	 *	get the relation object id	 * ----------------	 */	ValidateHacks();			/* XXX */	relationId = RelationGetRelid(relation);	/* ----------------	 *	 * ----------------	 */	if (relationId == MyRelationRelationId)		objectId = tuple->t_data->t_oid;	else if (relationId == MyAttributeRelationId)		objectId = ((Form_pg_attribute) GETSTRUCT(tuple))->attrelid;	else if (relationId == MyAMRelationId)		objectId = tuple->t_data->t_oid;	else if (relationId == MyAMOPRelationId)	{		;						/* objectId is unused */	}	else		return;	/* ----------------	 *	  can't handle immediate relation descriptor invalidation	 * ----------------	 */	Assert(PointerIsValid(function));	(*function) (relationId, objectId);}/* *	InitLocalInvalidateData * *	Setup this before anything could ever get invalid! *	Called by InitPostgres(); */voidInitLocalInvalidateData(){	ValidateHacks();}/* * DiscardInvalid *		Causes the invalidated cache state to be discarded. * * Note: *		This should be called as the first step in processing a transaction. *		This should be called while waiting for a query from the front end *		when other backends are active. */voidDiscardInvalid(){	/* ----------------	 *	debugging stuff	 * ----------------	 */#ifdef	INVALIDDEBUG	elog(DEBUG, "DiscardInvalid called");#endif	 /* defined(INVALIDDEBUG) */	InvalidateSharedInvalid(CacheIdInvalidate, ResetSystemCaches);}/* * RegisterInvalid *		Causes registration of invalidated state with other backends iff true. * * Note: *		This should be called as the last step in processing a transaction. */voidRegisterInvalid(bool send){	/* ----------------	 *	debugging stuff	 * ----------------	 */#ifdef	INVALIDDEBUG	elog(DEBUG, "RegisterInvalid(%d) called", send);#endif	 /* defined(INVALIDDEBUG) */	/* ----------------	 *	Note: Invalid is a global variable	 * ----------------	 */	if (send)		LocalInvalidInvalidate(Invalid,							   InvalidationMessageRegisterSharedInvalid);	else		LocalInvalidInvalidate(Invalid,							   InvalidationMessageCacheInvalidate);	Invalid = EmptyLocalInvalid;}/* * RelationIdInvalidateHeapTuple *		Causes the given tuple in a relation to be invalidated. * * Note: *		Assumes object id is valid. *		Assumes tuple is valid. */#ifdef	INVALIDDEBUG#define RelationInvalidateHeapTuple_DEBUG1 \elog(DEBUG, "RelationInvalidateHeapTuple(%s, [%d,%d])", \	 RelationGetRelationName(relation), \	 ItemPointerGetBlockNumber(&tuple->t_ctid), \	 ItemPointerGetOffsetNumber(&tuple->t_ctid))#else#define RelationInvalidateHeapTuple_DEBUG1#endif	 /* defined(INVALIDDEBUG) */voidRelationInvalidateHeapTuple(Relation relation, HeapTuple tuple){	/* ----------------	 *	sanity checks	 * ----------------	 */	Assert(RelationIsValid(relation));	Assert(HeapTupleIsValid(tuple));	if (IsBootstrapProcessingMode())		return;	/* ----------------	 *	this only works for system relations now	 * ----------------	 */	if (!IsSystemRelationName(RelationGetForm(relation)->relname.data))		return;	/* ----------------	 *	debugging stuff	 * ----------------	 */	RelationInvalidateHeapTuple_DEBUG1;	RelationInvalidateCatalogCacheTuple(relation,										tuple,										CacheIdRegisterLocalInvalid);	RelationInvalidateRelationCache(relation,									tuple,									RelationIdRegisterLocalInvalid);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -